diff --git a/.github/workflows/smoke.yaml b/.github/workflows/smoke.yaml index 59ff43a2..1a392a12 100644 --- a/.github/workflows/smoke.yaml +++ b/.github/workflows/smoke.yaml @@ -59,7 +59,7 @@ jobs: echo "run_smoke_tests=false" >> $GITHUB_OUTPUT - gpt-4o-2024-05-13: + gpt-4o-2024-08-06: needs: check-label if: ${{ needs.check-label.outputs.run_smoke_tests == 'true' }} runs-on: ubuntu-22.04 @@ -81,14 +81,14 @@ jobs: go-version: "1.21" - env: OPENAI_API_KEY: ${{ secrets.SMOKE_OPENAI_API_KEY }} - GPTSCRIPT_DEFAULT_MODEL: gpt-4o-2024-05-13 - name: Run smoke test for gpt-4o-2024-05-13 + GPTSCRIPT_DEFAULT_MODEL: gpt-4o-2024-08-06 + name: Run smoke test for gpt-4o-2024-08-06 run: | - echo "Running smoke test for model gpt-4o-2024-05-13" + echo "Running smoke test for model gpt-4o-2024-08-06" export PATH="$(pwd)/bin:${PATH}" make smoke - gpt-4-turbo-2024-04-09: + gpt-4o-mini-2024-07-18: needs: check-label if: ${{ needs.check-label.outputs.run_smoke_tests == 'true' }} runs-on: ubuntu-22.04 @@ -110,14 +110,14 @@ jobs: go-version: "1.21" - env: OPENAI_API_KEY: ${{ secrets.SMOKE_OPENAI_API_KEY }} - GPTSCRIPT_DEFAULT_MODEL: gpt-4-turbo-2024-04-09 - name: Run smoke test for gpt-4-turbo-2024-04-09 + GPTSCRIPT_DEFAULT_MODEL: gpt-4o-mini-2024-07-18 + name: Run smoke test for gpt-4o-mini-2024-07-18 run: | - echo "Running smoke test for model gpt-4-turbo-2024-04-09" + echo "Running smoke test for model gpt-4o-mini-2024-07-18" export PATH="$(pwd)/bin:${PATH}" make smoke - claude-3-5-sonnet-20240620: + claude-3-7-sonnet-20250219: needs: check-label if: ${{ needs.check-label.outputs.run_smoke_tests == 'true' }} runs-on: ubuntu-22.04 @@ -139,42 +139,11 @@ jobs: go-version: "1.21" - env: OPENAI_API_KEY: ${{ secrets.SMOKE_OPENAI_API_KEY }} - GPTSCRIPT_DEFAULT_MODEL: claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider + GPTSCRIPT_DEFAULT_MODEL: claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider ANTHROPIC_API_KEY: ${{ secrets.SMOKE_ANTHROPIC_API_KEY }} GPTSCRIPT_CREDENTIAL_OVERRIDE: "github.com/gptscript-ai/claude3-anthropic-provider/credential:ANTHROPIC_API_KEY" - name: Run smoke test for claude-3-5-sonnet-20240620 + name: Run smoke test for claude-3-7-sonnet-20250219 run: | - echo "Running smoke test for model claude-3-5-sonnet-20240620" - export PATH="$(pwd)/bin:${PATH}" - make smoke - - mistral-large-2402: - needs: check-label - if: ${{ needs.check-label.outputs.run_smoke_tests == 'true' }} - runs-on: ubuntu-22.04 - steps: - - name: Checkout base repository - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - name: Checkout PR code if running for a PR - if: ${{ github.event_name == 'pull_request_target' }} - uses: actions/checkout@v4 - with: - fetch-depth: 1 - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} - - uses: actions/setup-go@v5 - with: - cache: false - go-version: "1.21" - - env: - OPENAI_API_KEY: ${{ secrets.SMOKE_OPENAI_API_KEY }} - GPTSCRIPT_DEFAULT_MODEL: mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider - MISTRAL_API_KEY: ${{ secrets.SMOKE_MISTRAL_API_KEY }} - GPTSCRIPT_CREDENTIAL_OVERRIDE: "github.com/gptscript-ai/mistral-laplateforme-provider/credential:MISTRAL_API_KEY" - name: Run smoke test for mistral-large-2402 - run: | - echo "Running smoke test for model mistral-large-2402" + echo "Running smoke test for model claude-3-7-sonnet-20250219" export PATH="$(pwd)/bin:${PATH}" make smoke diff --git a/.gitignore b/.gitignore index 759e3286..32148f05 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /bin +/pkg/tests/bin /.idea /static/ui **/node_modules/ diff --git a/.golangci.yml b/.golangci.yml index e91a9ccc..0f992df5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,24 +1,41 @@ +version: "2" run: timeout: 5m - output: formats: - - format: colored-line-number - + text: + path: stdout linters: - disable-all: true + default: none enable: - - errcheck - - gofmt - - gosimple - - govet - - ineffassign - - staticcheck - - typecheck - - thelper - - unused - - goimports - - whitespace - - revive - fast: false + - errcheck + - govet + - ineffassign + - revive + - staticcheck + - thelper + - unused + - whitespace + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +issues: max-same-issues: 50 +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/.vscode/launch.json b/.vscode/launch.json index cc84991c..669016b3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,12 +15,12 @@ ] }, { - "name": "Launch Server", + "name": "Clicky Serves", "type": "go", "request": "launch", "mode": "debug", "program": "main.go", - "args": ["--server"] + "args": ["--debug", "--listen-address", "127.0.0.1:63774", "sys.sdkserver"] } ] } diff --git a/Makefile b/Makefile index 4a52694a..80ed0356 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ smoke: build smoke: go test -v -tags='smoke' ./pkg/tests/smoke/... -GOLANGCI_LINT_VERSION ?= v1.60.1 +GOLANGCI_LINT_VERSION ?= v2.6.1 lint: if ! command -v golangci-lint &> /dev/null; then \ echo "Could not find golangci-lint, installing version $(GOLANGCI_LINT_VERSION)."; \ @@ -49,11 +49,11 @@ serve-docs: # This will initialize the node_modules needed to run the docs dev server. Run this before running serve-docs init-docs: - docker run --rm --workdir=/docs -v $${PWD}/docs:/docs node:18-buster yarn install + docker run --rm --workdir=/docs -v $${PWD}/docs:/docs node:18-buster npm install # Ensure docs build without errors. Makes sure generated docs are in-sync with CLI. validate-docs: gen-docs - docker run --rm --workdir=/docs -v $${PWD}/docs:/docs node:18-buster yarn build + docker run --rm --workdir=/docs -v $${PWD}/docs:/docs node:18-buster npm run build if [ -n "$$(git status --porcelain --untracked-files=no)" ]; then \ git status --porcelain --untracked-files=no; \ echo "Encountered dirty repo!"; \ @@ -62,4 +62,4 @@ validate-docs: gen-docs ;fi gen-docs: - go run tools/gendocs/main.go \ No newline at end of file + go run tools/gendocs/main.go diff --git a/docs/docs/03-tools/02-authoring.md b/docs/docs/03-tools/02-authoring.md index b8757440..423147ab 100644 --- a/docs/docs/03-tools/02-authoring.md +++ b/docs/docs/03-tools/02-authoring.md @@ -90,15 +90,3 @@ Here are the supported languages and examples of tools written in those language | `Python` | [Image Generation](https://github.com/gptscript-ai/dalle-image-generation) - Generate images based on a prompt | | `Node.js` | [Vision](https://github.com/gptscript-ai/gpt4-v-vision) - Analyze and interpret images | | `Golang` | [Search](https://github.com/gptscript-ai/search) - Use various providers to search the internet | - - -## Automatic Documentation - -Each GPTScript tool is self-documented using the `tool.gpt` file. -You can automatically generate documentation for your tools by visiting `https://tools.gptscript.ai/`. -This documentation site allows others to easily search and explore the tools that have been created. - -You can add more information about how to use your tool by adding an `examples` directory to your repository and adding a collection of `.gpt` files that demonstrate how to use your tool. -These examples will be automatically included in the documentation. - -For more information and to explore existing tools, visit [tools.gptscript.ai](https://tools.gptscript.ai). diff --git a/docs/docs/03-tools/03-openapi.md b/docs/docs/03-tools/03-openapi.md index 0b0f4961..e99172eb 100644 --- a/docs/docs/03-tools/03-openapi.md +++ b/docs/docs/03-tools/03-openapi.md @@ -41,12 +41,6 @@ Will be resolved as `https://api.example.com/v1`. ## Authentication -:::warning -All authentication options will be completely ignored if the server uses HTTP and not HTTPS, unless the request is for `localhost` or 127.0.0.1. -This is to protect users from accidentally sending credentials in plain text. -HTTP is only OK, if it's on localhost/127.0.0.1. -::: - ### 1. Security Schemes GPTScript will read the defined [security schemes](https://swagger.io/docs/specification/authentication/) in the OpenAPI definition. The currently supported types are `apiKey` and `http`. diff --git a/docs/docs/04-command-line-reference/gptscript.md b/docs/docs/04-command-line-reference/gptscript.md index 8a726c64..4ca35228 100644 --- a/docs/docs/04-command-line-reference/gptscript.md +++ b/docs/docs/04-command-line-reference/gptscript.md @@ -43,6 +43,7 @@ gptscript [flags] PROGRAM_FILE [INPUT...] -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) --save-chat-state-file string A file to save the chat state to so that a conversation can be resumed with --chat-state ($GPTSCRIPT_SAVE_CHAT_STATE_FILE) --sub-tool string Use tool of this name, not the first tool in file ($GPTSCRIPT_SUB_TOOL) + --system-tools-dir string Directory that contains system managed tool for which GPTScript will not manage the runtime ($GPTSCRIPT_SYSTEM_TOOLS_DIR) --ui Launch the UI ($GPTSCRIPT_UI) --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` diff --git a/docs/docs/04-command-line-reference/gptscript_eval.md b/docs/docs/04-command-line-reference/gptscript_eval.md index 257cf609..ddbecc9f 100644 --- a/docs/docs/04-command-line-reference/gptscript_eval.md +++ b/docs/docs/04-command-line-reference/gptscript_eval.md @@ -46,6 +46,7 @@ gptscript eval [flags] --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --system-tools-dir string Directory that contains system managed tool for which GPTScript will not manage the runtime ($GPTSCRIPT_SYSTEM_TOOLS_DIR) --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` diff --git a/docs/docs/04-command-line-reference/gptscript_fmt.md b/docs/docs/04-command-line-reference/gptscript_fmt.md index 1175a1f1..2b042623 100644 --- a/docs/docs/04-command-line-reference/gptscript_fmt.md +++ b/docs/docs/04-command-line-reference/gptscript_fmt.md @@ -40,6 +40,7 @@ gptscript fmt [flags] --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --system-tools-dir string Directory that contains system managed tool for which GPTScript will not manage the runtime ($GPTSCRIPT_SYSTEM_TOOLS_DIR) --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` diff --git a/docs/docs/04-command-line-reference/gptscript_getenv.md b/docs/docs/04-command-line-reference/gptscript_getenv.md index 4a688439..7e677c5c 100644 --- a/docs/docs/04-command-line-reference/gptscript_getenv.md +++ b/docs/docs/04-command-line-reference/gptscript_getenv.md @@ -39,6 +39,7 @@ gptscript getenv [flags] KEY [DEFAULT] --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --system-tools-dir string Directory that contains system managed tool for which GPTScript will not manage the runtime ($GPTSCRIPT_SYSTEM_TOOLS_DIR) --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` diff --git a/docs/docs/04-command-line-reference/gptscript_parse.md b/docs/docs/04-command-line-reference/gptscript_parse.md index 66d2791c..567b0c05 100644 --- a/docs/docs/04-command-line-reference/gptscript_parse.md +++ b/docs/docs/04-command-line-reference/gptscript_parse.md @@ -40,6 +40,7 @@ gptscript parse [flags] --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --system-tools-dir string Directory that contains system managed tool for which GPTScript will not manage the runtime ($GPTSCRIPT_SYSTEM_TOOLS_DIR) --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 6a0eb3bc..f3344bca 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -70,11 +70,6 @@ const config = { label: "Contact Us", position: "right", }, - { - href: "https://tools.gptscript.ai/", - label: "Tool Search", - position: "right", - }, ], }, footer: { diff --git a/docs/package-lock.json b/docs/package-lock.json index 9bbb14b2..43b226ef 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -198,81 +198,19 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", @@ -602,17 +540,19 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -639,99 +579,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", - "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.27.3" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -2040,36 +1907,35 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.9.tgz", - "integrity": "sha512-oeOFTrYWdWXCvXGB5orvMTJ6gCZ9I6FBjR+M38iKNXCsPxr4xT0RTdg5uz1H7QP8pp74IzPtwritEr+JscqHXQ==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.6.tgz", + "integrity": "sha512-vDVrlmRAY8z9Ul/HxT+8ceAru95LQgkSKiXkSYZvqtbkPSfhZJgpRp45Cldbh1GJ1kxzQkI70AqyrTI58KpaWQ==", + "license": "MIT", "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" + "core-js-pure": "^3.30.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2096,13 +1962,13 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2834,9 +2700,10 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3359,9 +3226,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" }, "node_modules/@types/estree-jsx": { "version": "1.0.4", @@ -3648,145 +3516,162 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "1.3.8", @@ -3820,9 +3705,10 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3830,14 +3716,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -4198,20 +4076,21 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", + "qs": "6.13.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4224,6 +4103,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4232,6 +4112,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4239,7 +4120,8 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/bonjour-service": { "version": "1.2.1", @@ -4277,29 +4159,31 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "funding": [ { "type": "opencollective", @@ -4314,11 +4198,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -4394,6 +4279,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4434,9 +4348,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001589", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", - "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", "funding": [ { "type": "opencollective", @@ -4450,7 +4364,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/ccount": { "version": "2.0.1", @@ -4736,7 +4651,8 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" }, "node_modules/combine-promises": { "version": "1.2.0", @@ -4879,6 +4795,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4889,9 +4806,10 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5028,9 +4946,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5484,6 +5403,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5500,6 +5420,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -5676,6 +5597,20 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -5689,12 +5624,14 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.679", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.679.tgz", - "integrity": "sha512-NhQMsz5k0d6m9z3qAxnsOR/ebal4NAGsrNVRwcDo4Kc/zQ7KdsTKZUxZoygHcVRb0QDW3waEDIcE3isZ79RP6g==" + "version": "1.5.166", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz", + "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==", + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -5724,17 +5661,19 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5763,12 +5702,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -5786,10 +5723,23 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -5923,15 +5873,12 @@ } }, "node_modules/estree-util-value-to-estree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.0.1.tgz", - "integrity": "sha512-b2tdzTurEIbwRh+mKrEcaWfu1wgb8J1hVsgREg7FFiecWwK/PhO8X0kyc+0bIcKNtD4sqxIdNoRy6/p/TvECEA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.4.0.tgz", + "integrity": "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==", + "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "is-plain-obj": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" + "@types/estree": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/remcohaszing" @@ -5981,6 +5928,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6033,36 +5981,37 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -6071,6 +6020,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/content-disposition": { @@ -6098,9 +6051,10 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", @@ -6151,14 +6105,6 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dependencies": { - "punycode": "^1.3.2" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -6274,9 +6220,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6285,12 +6232,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -6305,6 +6253,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6312,7 +6261,8 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/find-cache-dir": { "version": "4.0.0", @@ -6353,15 +6303,16 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -6531,6 +6482,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6588,15 +6540,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6610,6 +6568,19 @@ "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -6659,7 +6630,8 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" }, "node_modules/global-dirs": { "version": "3.0.1", @@ -6746,11 +6718,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6868,21 +6841,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6902,9 +6865,10 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -7310,6 +7274,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -7340,9 +7305,10 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -7397,6 +7363,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -7424,9 +7391,10 @@ } }, "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", "dependencies": { "queue": "6.0.2" }, @@ -7698,6 +7666,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -8140,6 +8109,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdast-util-directive": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", @@ -8527,6 +8505,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8543,9 +8522,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -10240,11 +10223,12 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -10255,6 +10239,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -10369,15 +10354,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -10430,9 +10416,10 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -10497,9 +10484,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10538,6 +10529,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -10827,9 +10819,10 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", "dependencies": { "isarray": "0.0.1" } @@ -10853,9 +10846,10 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -11570,9 +11564,10 @@ } }, "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", "engines": { "node": ">=6" } @@ -11638,11 +11633,6 @@ "node": ">= 0.10" } }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -11658,11 +11648,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -11726,9 +11717,10 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -11743,6 +11735,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -12095,11 +12088,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", @@ -12569,7 +12557,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sax": { "version": "1.3.0", @@ -12585,9 +12574,10 @@ } }, "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -12595,7 +12585,7 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -12682,9 +12672,10 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -12708,6 +12699,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -12715,17 +12707,29 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12739,24 +12743,25 @@ } }, "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "license": "MIT", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", "mime-types": "2.1.18", "minimatch": "3.1.2", "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", + "path-to-regexp": "3.3.0", "range-parser": "1.2.0" } }, "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" }, "node_modules/serve-index": { "version": "1.9.1", @@ -12829,14 +12834,15 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -12861,7 +12867,8 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -12923,14 +12930,69 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -13118,6 +13180,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -13390,12 +13453,13 @@ } }, "node_modules/terser": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.2.tgz", - "integrity": "sha512-sHXmLSkImesJ4p5apTeT63DsV4Obe1s37qT8qvwHRmVxKTBH7Rv9Wr26VcAMmLbmk9UliiwK8z+657NyJHHy/w==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz", + "integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==", + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -13407,15 +13471,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -13439,29 +13504,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -13475,28 +13517,6 @@ "node": ">= 10.13.0" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -13536,18 +13556,11 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -13559,6 +13572,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -13609,6 +13623,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -13621,6 +13636,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13629,6 +13645,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -13838,14 +13855,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -13860,9 +13878,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -14135,9 +14154,10 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -14164,33 +14184,34 @@ } }, "node_modules/webpack": { - "version": "5.90.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", - "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", + "version": "5.99.9", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", + "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -14244,9 +14265,10 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -14269,6 +14291,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14277,6 +14300,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -14288,14 +14312,16 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -14325,7 +14351,7 @@ "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", + "webpack-dev-middleware": "^5.3.4", "ws": "^8.13.0" }, "bin": { @@ -14351,9 +14377,10 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -14391,34 +14418,6 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/webpack/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -14438,23 +14437,6 @@ "node": ">= 0.6" } }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webpackbar": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", @@ -14595,9 +14577,10 @@ } }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", "engines": { "node": ">=8.3.0" }, diff --git a/go.mod b/go.mod index 4a95a521..e4369567 100644 --- a/go.mod +++ b/go.mod @@ -1,39 +1,43 @@ module github.com/gptscript-ai/gptscript -go 1.23.1 +go 1.25.3 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 - github.com/adrg/xdg v0.4.0 + github.com/adrg/xdg v0.5.3 github.com/chzyer/readline v1.5.1 github.com/docker/cli v26.0.0+incompatible github.com/docker/docker-credential-helpers v0.8.1 - github.com/fatih/color v1.17.0 - github.com/getkin/kin-openapi v0.124.0 - github.com/go-git/go-git/v5 v5.12.0 + github.com/fatih/color v1.18.0 + github.com/getkin/kin-openapi v0.132.0 + github.com/go-git/go-git/v5 v5.13.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86 - github.com/gptscript-ai/chat-completion-client v0.0.0-20240813051153-a440ada7e3c3 - github.com/gptscript-ai/cmd v0.0.0-20240802230653-326b7baf6fcb - github.com/gptscript-ai/go-gptscript v0.9.5-rc5.0.20240927213153-2af51434b93e - github.com/gptscript-ai/tui v0.0.0-20240923192013-172e51ccf1d6 - github.com/hexops/autogold/v2 v2.2.1 - github.com/hexops/valast v1.4.4 + github.com/gptscript-ai/chat-completion-client v0.0.0-20250224164718-139cb4507b1d + github.com/gptscript-ai/cmd v0.0.0-20250530150401-bc71fddf8070 + github.com/gptscript-ai/go-gptscript v0.9.6-0.20250714170123-17ad44ae8c54 + github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9 + github.com/hexops/autogold/v2 v2.3.0 + github.com/hexops/valast v1.5.0 github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 - github.com/mholt/archiver/v4 v4.0.0-alpha.8 + github.com/mholt/archives v0.1.5 + github.com/modelcontextprotocol/go-sdk v0.2.0 + github.com/nanobot-ai/nanobot v0.0.6-0.20250825141756-f61b8b0f41f8 + github.com/pkoukk/tiktoken-go v0.1.7 + github.com/pkoukk/tiktoken-go-loader v0.0.2-0.20240522064338-c17e8bc0f699 github.com/rs/cors v1.11.0 github.com/samber/lo v1.38.1 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.8.0 - github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.9.0 + github.com/spf13/cobra v1.9.1 + github.com/spf13/pflag v1.0.6 + github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.17.1 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc - golang.org/x/sync v0.7.0 - golang.org/x/term v0.22.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/sync v0.17.0 + golang.org/x/term v0.34.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 sigs.k8s.io/yaml v1.4.0 @@ -45,89 +49,99 @@ require ( atomicgo.dev/schedule v0.1.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/STARRY-S/zip v0.2.3 // indirect github.com/alecthomas/chroma/v2 v2.8.0 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.2.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/bodgit/plumbing v1.2.0 // indirect - github.com/bodgit/sevenzip v1.3.0 // indirect - github.com/bodgit/windows v1.0.0 // indirect + github.com/bodgit/plumbing v1.3.0 // indirect + github.com/bodgit/sevenzip v1.6.1 // indirect + github.com/bodgit/windows v1.0.1 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/glamour v0.7.0 // indirect - github.com/charmbracelet/lipgloss v0.11.0 // indirect - github.com/charmbracelet/x/ansi v0.1.1 // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect - github.com/connesc/cipherio v0.2.1 // indirect github.com/containerd/console v1.0.4 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/creack/pty v1.1.24 // indirect + github.com/cyphar/filepath-securejoin v0.2.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/dsnet/compress v0.0.1 // indirect + github.com/dlclark/regexp2 v1.11.4 // indirect + github.com/dop251/goja v0.0.0-20250531102226-cb187b08699c // indirect + github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.5.0 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/swag v0.22.8 // indirect + github.com/go-git/go-billy/v5 v5.6.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/css v1.0.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hexops/autogold v1.3.1 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/invopop/yaml v0.2.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.16.5 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mikelolasagasti/xz v1.0.1 // indirect + github.com/minio/minlz v1.0.1 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/nightlyone/lockfile v1.0.0 // indirect - github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect + github.com/nwaples/rardecode/v2 v2.2.0 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect - github.com/pierrec/lz4/v4 v4.1.15 // indirect + github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pterm/pterm v0.12.79 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.2.2 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect + github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e // indirect + github.com/spf13/afero v1.15.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/goldmark v1.5.4 // indirect github.com/yuin/goldmark-emoji v1.0.2 // indirect - go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.23.0 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - mvdan.cc/gofumpt v0.6.0 // indirect + mvdan.cc/gofumpt v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index 80cbcea1..33a5e3c1 100644 --- a/go.sum +++ b/go.sum @@ -40,23 +40,27 @@ github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/ github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= -github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= -github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= +github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4= +github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk= +github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= +github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/chroma/v2 v2.8.0 h1:w9WJUjFFmHHB2e8mRpL9jjy3alYDlU0QLDezj1xE264= github.com/alecthomas/chroma/v2 v2.8.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= +github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -66,20 +70,25 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/bodgit/plumbing v1.2.0 h1:gg4haxoKphLjml+tgnecR4yLBV5zo4HAZGCtAh3xCzM= -github.com/bodgit/plumbing v1.2.0/go.mod h1:b9TeRi7Hvc6Y05rjm8VML3+47n4XTZPtQ/5ghqic2n8= -github.com/bodgit/sevenzip v1.3.0 h1:1ljgELgtHqvgIp8W8kgeEGHIWP4ch3xGI8uOBZgLVKY= -github.com/bodgit/sevenzip v1.3.0/go.mod h1:omwNcgZTEooWM8gA/IJ2Nk/+ZQ94+GsytRzOJJ8FBlM= -github.com/bodgit/windows v1.0.0 h1:rLQ/XjsleZvx4fR1tB/UxQrK+SJ2OFHzfPjLWWOhDIA= -github.com/bodgit/windows v1.0.0/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= +github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= +github.com/bodgit/sevenzip v1.6.1 h1:kikg2pUMYC9ljU7W9SaqHXhym5HyKm8/M/jd31fYan4= +github.com/bodgit/sevenzip v1.6.1/go.mod h1:GVoYQbEVbOGT8n2pfqCIMRUaRjQ8F9oSqoBEqZh5fQ8= +github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= +github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= github.com/charmbracelet/glamour v0.7.0/go.mod h1:jUMh5MeihljJPQbJ/wf4ldw2+yBP59+ctV36jASy7ps= -github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= -github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= -github.com/charmbracelet/x/ansi v0.1.1 h1:CGAduulr6egay/YVbGc8Hsu8deMg1xZ/bkaXTPi1JDk= -github.com/charmbracelet/x/ansi v0.1.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -90,65 +99,65 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw= -github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= +github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= -github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= +github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dop251/goja v0.0.0-20250531102226-cb187b08699c h1:In87uFQZsuGfjDDNfWnzMVY6JVTwc8XYMl6W2DAmNjk= +github.com/dop251/goja v0.0.0-20250531102226-cb187b08699c/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= +github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug= +github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M= -github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM= -github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= -github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= -github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= +github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= -github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= +github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw= -github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -161,14 +170,10 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -176,15 +181,18 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -200,37 +208,33 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86 h1:m9yLtIEd0z1ia8qFjq3u0Ozb6QKwidyL856JLJp6nbA= github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86/go.mod h1:lK3K5EZx4dyT24UG3yCt0wmspkYqrj4D/8kxdN3relk= -github.com/gptscript-ai/chat-completion-client v0.0.0-20240813051153-a440ada7e3c3 h1:EQiFTZv+BnOWJX2B9XdF09fL2Zj7h19n1l23TpWCafc= -github.com/gptscript-ai/chat-completion-client v0.0.0-20240813051153-a440ada7e3c3/go.mod h1:7P/o6/IWa1KqsntVf68hSnLKuu3+xuqm6lYhch1w4jo= -github.com/gptscript-ai/cmd v0.0.0-20240802230653-326b7baf6fcb h1:ky2J2CzBOskC7Jgm2VJAQi2x3p7FVGa+2/PcywkFJuc= -github.com/gptscript-ai/cmd v0.0.0-20240802230653-326b7baf6fcb/go.mod h1:DJAo1xTht1LDkNYFNydVjTHd576TC7MlpsVRl3oloVw= -github.com/gptscript-ai/go-gptscript v0.9.5-rc5.0.20240927213153-2af51434b93e h1:WpNae0NBx+Ri8RB3SxF8DhadDKU7h+jfWPQterDpbJA= -github.com/gptscript-ai/go-gptscript v0.9.5-rc5.0.20240927213153-2af51434b93e/go.mod h1:/FVuLwhz+sIfsWUgUHWKi32qT0i6+IXlUlzs70KKt/Q= -github.com/gptscript-ai/tui v0.0.0-20240923192013-172e51ccf1d6 h1:vkgNZVWQgbE33VD3z9WKDwuu7B/eJVVMMPM62ixfCR8= -github.com/gptscript-ai/tui v0.0.0-20240923192013-172e51ccf1d6/go.mod h1:frrl/B+ZH3VSs3Tqk2qxEIIWTONExX3tuUa4JsVnqx4= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/gptscript-ai/chat-completion-client v0.0.0-20250224164718-139cb4507b1d h1:p5uqZufDIMQzAALblZFkr8fwbnZbFXbBCR1ZMAFylXk= +github.com/gptscript-ai/chat-completion-client v0.0.0-20250224164718-139cb4507b1d/go.mod h1:7P/o6/IWa1KqsntVf68hSnLKuu3+xuqm6lYhch1w4jo= +github.com/gptscript-ai/cmd v0.0.0-20250530150401-bc71fddf8070 h1:xm5ZZFraWFwxyE7TBEncCXArubCDZTwG6s5bpMzqhSY= +github.com/gptscript-ai/cmd v0.0.0-20250530150401-bc71fddf8070/go.mod h1:DJAo1xTht1LDkNYFNydVjTHd576TC7MlpsVRl3oloVw= +github.com/gptscript-ai/go-gptscript v0.9.6-0.20250714170123-17ad44ae8c54 h1:9OAiDBdOQUHVL89wmb38+/XOuewboMhgnk6NqoJiC00= +github.com/gptscript-ai/go-gptscript v0.9.6-0.20250714170123-17ad44ae8c54/go.mod h1:HLPvKBhDtsEkyyUWefJVhPpl98R3tZG6ps7+mQ+EKVI= +github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9 h1:wQC8sKyeGA50WnCEG+Jo5FNRIkuX3HX8d3ubyWCCoI8= +github.com/gptscript-ai/tui v0.0.0-20250419050840-5e79e16786c9/go.mod h1:iwHxuueg2paOak7zIg0ESBWx7A0wIHGopAratbgaPNY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hexops/autogold v0.8.1/go.mod h1:97HLDXyG23akzAoRYJh/2OBs3kd80eHyKPvZw0S5ZBY= github.com/hexops/autogold v1.3.1 h1:YgxF9OHWbEIUjhDbpnLhgVsjUDsiHDTyDfy2lrfdlzo= github.com/hexops/autogold v1.3.1/go.mod h1:sQO+mQUCVfxOKPht+ipDSkJ2SCJ7BNJVHZexsXqWMx4= -github.com/hexops/autogold/v2 v2.2.1 h1:JPUXuZQGkcQMv7eeDXuNMovjfoRYaa0yVcm+F3voaGY= -github.com/hexops/autogold/v2 v2.2.1/go.mod h1:IJwxtUfj1BGLm0YsR/k+dIxYi6xbeLjqGke2bzcOTMI= +github.com/hexops/autogold/v2 v2.3.0 h1:tObVFzC7WDIF2tT80Bo9p42mXlkqcyLKmIMghcjoTWE= +github.com/hexops/autogold/v2 v2.3.0/go.mod h1:e77HQw5vjubldctJpHjjDHr7KHUmrFc5KrWKFFieO7Q= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hexops/valast v1.4.3/go.mod h1:Iqx2kLj3Jn47wuXpj3wX40xn6F93QNFBHuiKBerkTGA= -github.com/hexops/valast v1.4.4 h1:rETyycw+/L2ZVJHHNxEBgh8KUn+87WugH9MxcEv9PGs= -github.com/hexops/valast v1.4.4/go.mod h1:Jcy1pNH7LNraVaAZDLyv21hHg2WBv9Nf9FL6fGxU7o4= +github.com/hexops/valast v1.5.0 h1:FBTuvVi0wjTngtXJRZXMbkN/Dn6DgsUsBwch2DUJU8Y= +github.com/hexops/valast v1.5.0/go.mod h1:Jcy1pNH7LNraVaAZDLyv21hHg2WBv9Nf9FL6fGxU7o4= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= -github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -245,8 +249,8 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -254,8 +258,8 @@ github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuOb github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -272,50 +276,65 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM= -github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A= +github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ= +github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= +github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= +github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A= +github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= +github.com/modelcontextprotocol/go-sdk v0.2.0 h1:PESNYOmyM1c369tRkzXLY5hHrazj8x9CY1Xu0fLCryM= +github.com/modelcontextprotocol/go-sdk v0.2.0/go.mod h1:0sL9zUKKs2FTTkeCCVnKqbLJTw5TScefPAzojjU459E= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/nanobot-ai/nanobot v0.0.6-0.20250825141756-f61b8b0f41f8 h1:SZsity7OCSBRVnqfPMpmaSnaIFlMUm3z8sGED5C31XU= +github.com/nanobot-ai/nanobot v0.0.6-0.20250825141756-f61b8b0f41f8/go.mod h1:vKoxU5Fro4DuvHq2AsxjhNYF3/KRlAuHLFT+NZ9ns5w= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= github.com/nightlyone/lockfile v1.0.0/go.mod h1:rywoIealpdNse2r832aiD9jRk8ErCatROs6LzC841CI= -github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk= -github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= +github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= +github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77 h1:3bMMZ1f+GPXFQ1uNaYbO/uECWvSfqEA+ZEXn1rFAT88= github.com/olekukonko/tablewriter v0.0.6-0.20230925090304-df64c4bbad77/go.mod h1:8Hf+pH6thup1sPZPD+NLg7d6vbpsdilu9CPIeikvgMQ= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= +github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkoukk/tiktoken-go v0.1.7 h1:qOBHXX4PHtvIvmOtyg1EeKlwFRiMKAcoMp4Q+bLQDmw= +github.com/pkoukk/tiktoken-go v0.1.7/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg= +github.com/pkoukk/tiktoken-go-loader v0.0.2-0.20240522064338-c17e8bc0f699 h1:Sp8yiuxsitkmCfEvUnmNf8wzuZwlGNkRjI2yF0C3QUQ= +github.com/pkoukk/tiktoken-go-loader v0.0.2-0.20240522064338-c17e8bc0f699/go.mod h1:4mIkYyZooFlnenDlormIo6cd5wrlUKNr97wp9nGgEKo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -335,9 +354,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -351,27 +369,35 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= -github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= +github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU= github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e h1:H+jDTUeF+SVd4ApwnSFoew8ZwGNRfgb9EsZc7LcocAg= github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e/go.mod h1:VsUklG6OQo7Ctunu0gS3AtEOCEc2kMB6r5rKzxAes58= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= -github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -380,9 +406,9 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= @@ -394,6 +420,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU= @@ -404,19 +432,16 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= -go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= +go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= +go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -425,8 +450,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -447,10 +472,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -464,24 +487,21 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -491,9 +511,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -517,7 +536,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -526,28 +544,19 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -558,11 +567,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -592,10 +599,8 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -642,10 +647,10 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= @@ -656,9 +661,8 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= -mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= -mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= -mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= +mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= +mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/integration/cred_test.go b/integration/cred_test.go index 1ea73d35..a32e50e9 100644 --- a/integration/cred_test.go +++ b/integration/cred_test.go @@ -14,22 +14,6 @@ func TestGPTScriptCredential(t *testing.T) { require.Contains(t, out, "CREDENTIAL") } -// TestCredentialScopes makes sure that environment variables set by credential tools and shared credential tools -// are only available to the correct tools. See scripts/credscopes.gpt for more details. -func TestCredentialScopes(t *testing.T) { - out, err := RunScript("scripts/cred_scopes.gpt", "--sub-tool", "oneOne") - require.NoError(t, err) - require.Contains(t, out, "good") - - out, err = RunScript("scripts/cred_scopes.gpt", "--sub-tool", "twoOne") - require.NoError(t, err) - require.Contains(t, out, "good") - - out, err = RunScript("scripts/cred_scopes.gpt", "--sub-tool", "twoTwo") - require.NoError(t, err) - require.Contains(t, out, "good") -} - // TestCredentialExpirationEnv tests a GPTScript with two credentials that expire at different times. // One expires after two hours, and the other expires after one hour. // This test makes sure that the GPTSCRIPT_CREDENTIAL_EXPIRATION environment variable is set to the nearer expiration time (1h). diff --git a/integration/scripts/cred_scopes.gpt b/integration/scripts/cred_scopes.gpt deleted file mode 100644 index dc8e24e7..00000000 --- a/integration/scripts/cred_scopes.gpt +++ /dev/null @@ -1,160 +0,0 @@ -# This script sets up a chain of tools in a tree structure. -# The root is oneOne, with children twoOne and twoTwo, with children threeOne, threeTwo, and threeThree, with only -# threeTwo shared between them. -# Each tool should only have access to any credentials it defines and any credentials exported/shared by its -# immediate children (but not grandchildren). -# This script checks to make sure that this is working properly. -name: oneOne -tools: twoOne, twoTwo -cred: getcred with oneOne as var and 11 as val - -#!python3 - -import os - -oneOne = os.getenv('oneOne') -twoOne = os.getenv('twoOne') -twoTwo = os.getenv('twoTwo') -threeOne = os.getenv('threeOne') -threeTwo = os.getenv('threeTwo') -threeThree = os.getenv('threeThree') - -if oneOne != '11': - print('error: oneOne is not 11') - exit(1) - -if twoOne != '21': - print('error: twoOne is not 21') - exit(1) - -if twoTwo != '22': - print('error: twoTwo is not 22') - exit(1) - -if threeOne is not None: - print('error: threeOne is not None') - exit(1) - -if threeTwo is not None: - print('error: threeTwo is not None') - exit(1) - -if threeThree is not None: - print('error: threeThree is not None') - exit(1) - -print('good') - ---- -name: twoOne -tools: threeOne, threeTwo -sharecred: getcred with twoOne as var and 21 as val - -#!python3 - -import os - -oneOne = os.getenv('oneOne') -twoOne = os.getenv('twoOne') -twoTwo = os.getenv('twoTwo') -threeOne = os.getenv('threeOne') -threeTwo = os.getenv('threeTwo') -threeThree = os.getenv('threeThree') - -if oneOne is not None: - print('error: oneOne is not None') - exit(1) - -if twoOne is not None: - print('error: twoOne is not None') - exit(1) - -if twoTwo is not None: - print('error: twoTwo is not None') - exit(1) - -if threeOne != '31': - print('error: threeOne is not 31') - exit(1) - -if threeTwo != '32': - print('error: threeTwo is not 32') - exit(1) - -if threeThree is not None: - print('error: threeThree is not None') - exit(1) - -print('good') - ---- -name: twoTwo -tools: threeTwo, threeThree -sharecred: getcred with twoTwo as var and 22 as val - -#!python3 - -import os - -oneOne = os.getenv('oneOne') -twoOne = os.getenv('twoOne') -twoTwo = os.getenv('twoTwo') -threeOne = os.getenv('threeOne') -threeTwo = os.getenv('threeTwo') -threeThree = os.getenv('threeThree') - -if oneOne is not None: - print('error: oneOne is not None') - exit(1) - -if twoOne is not None: - print('error: twoOne is not None') - exit(1) - -if twoTwo is not None: - print('error: twoTwo is not None') - exit(1) - -if threeOne is not None: - print('error: threeOne is not None') - exit(1) - -if threeTwo != '32': - print('error: threeTwo is not 32') - exit(1) - -if threeThree != '33': - print('error: threeThree is not 33') - exit(1) - -print('good') - ---- -name: threeOne -sharecred: getcred with threeOne as var and 31 as val - ---- -name: threeTwo -sharecred: getcred with threeTwo as var and 32 as val - ---- -name: threeThree -sharecred: getcred with threeThree as var and 33 as val - ---- -name: getcred - -#!python3 - -import os -import json - -var = os.getenv('VAR') -val = os.getenv('VAL') - -output = { - "env": { - var: val - } -} -print(json.dumps(output)) diff --git a/pkg/assemble/assemble.go b/pkg/assemble/assemble.go deleted file mode 100644 index ad44d1dd..00000000 --- a/pkg/assemble/assemble.go +++ /dev/null @@ -1,17 +0,0 @@ -package assemble - -import ( - "encoding/json" - "io" - - "github.com/gptscript-ai/gptscript/pkg/types" -) - -var Header = []byte("GPTSCRIPT!") - -func Assemble(prg types.Program, output io.Writer) error { - if _, err := output.Write(Header); err != nil { - return err - } - return json.NewEncoder(output).Encode(prg) -} diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 5c818902..0a664b4d 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -23,7 +23,7 @@ func Authorize(ctx engine.Context, input string) (runner.AuthorizerResponse, err var result bool err := survey.AskOne(&survey.Confirm{ - Help: fmt.Sprintf("The full source of the tools is as follows:\n\n%s", ctx.Tool.String()), + Help: fmt.Sprintf("The full source of the tools is as follows:\n\n%s", ctx.Tool.Print()), Default: true, Message: ConfirmMessage(ctx, input), }, &result) diff --git a/pkg/builtin/builtin.go b/pkg/builtin/builtin.go index c17f2c80..b339b52a 100644 --- a/pkg/builtin/builtin.go +++ b/pkg/builtin/builtin.go @@ -269,18 +269,19 @@ func ListTools() (result []types.Tool) { sort.Strings(keys) for _, key := range keys { - t, _ := Builtin(key) + t, _ := DefaultModel(key, "") result = append(result, t) } return } -func Builtin(name string) (types.Tool, bool) { +func DefaultModel(name, defaultModel string) (types.Tool, bool) { // Legacy syntax not used anymore name = strings.TrimSuffix(name, "?") t, ok := tools[name] - t.Parameters.Name = name + t.Name = name + t.ModelName = defaultModel t.ID = name t.Instructions = "#!" + name return SetDefaults(t), ok @@ -327,7 +328,7 @@ func SysFind(_ context.Context, _ []string, input string, _ chan<- string) (stri return strings.Join(result, "\n"), nil } -func SysExec(_ context.Context, env []string, input string, progress chan<- string) (string, error) { +func SysExec(ctx context.Context, env []string, input string, progress chan<- string) (string, error) { var params struct { Command string `json:"command,omitempty"` Directory string `json:"directory,omitempty"` @@ -340,14 +341,20 @@ func SysExec(_ context.Context, env []string, input string, progress chan<- stri params.Directory = "." } + commandCtx, _ := engine.FromContext(ctx) + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + commandCtx.OnUserCancel(ctx, cancel) + log.Debugf("Running %s in %s", params.Command, params.Directory) var cmd *exec.Cmd - if runtime.GOOS == "windows" { - cmd = exec.Command("cmd.exe", "/c", params.Command) + cmd = exec.CommandContext(ctx, "cmd.exe", "/c", params.Command) } else { - cmd = exec.Command("/bin/sh", "-c", params.Command) + cmd = exec.CommandContext(ctx, "/bin/sh", "-c", params.Command) } var ( @@ -366,7 +373,8 @@ func SysExec(_ context.Context, env []string, input string, progress chan<- stri cmd.Dir = params.Directory cmd.Stdout = combined cmd.Stderr = combined - if err := cmd.Run(); err != nil { + if err := cmd.Run(); err != nil && (ctx.Err() == nil || commandCtx.Ctx.Err() != nil) { + // If the command failed and the context hasn't been canceled, then return the error. return fmt.Sprintf("ERROR: %s\nOUTPUT:\n%s", err, &out), nil } return out.String(), nil @@ -415,7 +423,6 @@ func getWorkspaceEnvFileContents(envs []string) ([]string, error) { } return envContents, nil - } func getWorkspaceDir(envs []string) (string, error) { @@ -660,6 +667,7 @@ func DiscardProgress() (progress chan<- string, closeFunc func()) { ch := make(chan string) go func() { for range ch { + continue } }() return ch, func() { @@ -695,9 +703,9 @@ func invalidArgument(input string, err error) string { return fmt.Sprintf("Failed to parse arguments %s: %v", input, err) } -func SysModelProviderCredential(ctx context.Context, _ []string, _ string, _ chan<- string) (string, error) { +func SysModelProviderCredential(ctx context.Context, env []string, _ string, _ chan<- string) (string, error) { engineContext, _ := engine.FromContext(ctx) - auth, url, err := engineContext.Engine.Model.ProxyInfo() + auth, url, err := engineContext.Engine.Model.ProxyInfo(env) if err != nil { return "", err } @@ -784,7 +792,7 @@ func SysChatFinish(_ context.Context, _ []string, input string, _ chan<- string) var params struct { Message string `json:"return,omitempty"` } - if err := json.Unmarshal([]byte(input), ¶ms); err != nil { + if err := json.Unmarshal([]byte(input), ¶ms); err != nil || params.Message == "" { return "", &engine.ErrChatFinish{ Message: input, } diff --git a/pkg/builtin/defaults.go b/pkg/builtin/defaults.go index ac264ae6..85bdf485 100644 --- a/pkg/builtin/defaults.go +++ b/pkg/builtin/defaults.go @@ -18,8 +18,8 @@ func SetDefaultModel(model string) { } func SetDefaults(tool types.Tool) types.Tool { - if tool.Parameters.ModelName == "" { - tool.Parameters.ModelName = GetDefaultModel() + if tool.ModelName == "" { + tool.ModelName = GetDefaultModel() } return tool } diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 031bd166..e5b4494e 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -92,6 +92,7 @@ func (c *Client) CacheDir() string { func (c *Client) cacheKey(key any) (string, error) { hash := sha256.New() + hash.Write([]byte("v2")) if err := json.NewEncoder(hash).Encode(key); err != nil { return "", err } @@ -104,6 +105,13 @@ func (c *Client) Store(ctx context.Context, key, value any) error { return nil } + select { + // If the context has been canceled, then don't try to save. + case <-ctx.Done(): + return nil + default: + } + if c.noop || IsNoCache(ctx) { keyValue, err := c.cacheKey(key) if err == nil { diff --git a/pkg/chat/chat.go b/pkg/chat/chat.go index a3fdb97a..5adc0676 100644 --- a/pkg/chat/chat.go +++ b/pkg/chat/chat.go @@ -17,7 +17,7 @@ type Prompter interface { } type Chatter interface { - Chat(ctx context.Context, prevState runner.ChatState, prg types.Program, env []string, input string) (resp runner.ChatResponse, err error) + Chat(ctx context.Context, prevState runner.ChatState, prg types.Program, env []string, input string, opts runner.RunOptions) (resp runner.ChatResponse, err error) } type GetProgram func() (types.Program, error) @@ -51,25 +51,30 @@ func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg resp runner.ChatResponse ) - prg, err := prg() + prog, err := prg() if err != nil { return err } - prompter.SetPrompt(getPrompt(prg, prevResp)) + prompter.SetPrompt(getPrompt(prog, prevResp)) if startInput != "" { input = startInput startInput = "" - } else if targetTool := prg.ToolSet[prg.EntryToolID]; !((prevState == nil || prevState == "") && targetTool.Arguments == nil && targetTool.Instructions != "") { + } else if targetTool := prog.ToolSet[prog.EntryToolID]; prevState != nil && prevState != "" || targetTool.Arguments != nil || targetTool.Instructions == "" { // The above logic will skip prompting if this is the first loop and the chat expects no args input, ok, err = prompter.Readline() if !ok || err != nil { return err } + + prog, err = prg() + if err != nil { + return err + } } - resp, err = chatter.Chat(ctx, prevState, prg, env, input) + resp, err = chatter.Chat(ctx, prevState, prog, env, input, runner.RunOptions{}) if err != nil { return err } diff --git a/pkg/cli/credential.go b/pkg/cli/credential.go index 674160b9..866ed4e5 100644 --- a/pkg/cli/credential.go +++ b/pkg/cli/credential.go @@ -9,10 +9,8 @@ import ( "time" cmd2 "github.com/gptscript-ai/cmd" - "github.com/gptscript-ai/gptscript/pkg/config" "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/gptscript" - "github.com/gptscript-ai/gptscript/pkg/repos/runtimes" "github.com/spf13/cobra" ) @@ -37,33 +35,24 @@ func (c *Credential) Customize(cmd *cobra.Command) { } func (c *Credential) Run(cmd *cobra.Command, _ []string) error { - cfg, err := config.ReadCLIConfig(c.root.ConfigFile) - if err != nil { - return fmt.Errorf("failed to read CLI config: %w", err) - } - opts, err := c.root.NewGPTScriptOpts() if err != nil { return err } - opts = gptscript.Complete(opts) - if opts.Runner.RuntimeManager == nil { - opts.Runner.RuntimeManager = runtimes.Default(opts.Cache.CacheDir) + gptScript, err := gptscript.New(cmd.Context(), opts) + if err != nil { + return err } + defer gptScript.Close(true) - ctxs := opts.CredentialContexts + credCtxs := gptScript.DefaultCredentialContexts if c.AllContexts { - ctxs = []string{credentials.AllCredentialContexts} + credCtxs = []string{credentials.AllCredentialContexts} } - if err = opts.Runner.RuntimeManager.SetUpCredentialHelpers(cmd.Context(), cfg); err != nil { - return err - } - - // Initialize the credential store and get all the credentials. - store, err := credentials.NewStore(cfg, opts.Runner.RuntimeManager, ctxs, opts.Cache.CacheDir) + store, err := gptScript.CredentialStoreFactory.NewStore(credCtxs) if err != nil { - return fmt.Errorf("failed to get credentials store: %w", err) + return err } creds, err := store.List(cmd.Context()) diff --git a/pkg/cli/credential_delete.go b/pkg/cli/credential_delete.go index b17ae851..6c43a41b 100644 --- a/pkg/cli/credential_delete.go +++ b/pkg/cli/credential_delete.go @@ -3,10 +3,7 @@ package cli import ( "fmt" - "github.com/gptscript-ai/gptscript/pkg/config" - "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/gptscript" - "github.com/gptscript-ai/gptscript/pkg/repos/runtimes" "github.com/spf13/cobra" ) @@ -28,23 +25,15 @@ func (c *Delete) Run(cmd *cobra.Command, args []string) error { return err } - cfg, err := config.ReadCLIConfig(c.root.ConfigFile) + gptScript, err := gptscript.New(cmd.Context(), opts) if err != nil { - return fmt.Errorf("failed to read CLI config: %w", err) - } - - opts = gptscript.Complete(opts) - if opts.Runner.RuntimeManager == nil { - opts.Runner.RuntimeManager = runtimes.Default(opts.Cache.CacheDir) - } - - if err = opts.Runner.RuntimeManager.SetUpCredentialHelpers(cmd.Context(), cfg); err != nil { return err } + defer gptScript.Close(true) - store, err := credentials.NewStore(cfg, opts.Runner.RuntimeManager, opts.CredentialContexts, opts.Cache.CacheDir) + store, err := gptScript.CredentialStoreFactory.NewStore(gptScript.DefaultCredentialContexts) if err != nil { - return fmt.Errorf("failed to get credentials store: %w", err) + return err } if err = store.Remove(cmd.Context(), args[0]); err != nil { diff --git a/pkg/cli/credential_show.go b/pkg/cli/credential_show.go index d8ea980b..95cb4f11 100644 --- a/pkg/cli/credential_show.go +++ b/pkg/cli/credential_show.go @@ -5,10 +5,7 @@ import ( "os" "text/tabwriter" - "github.com/gptscript-ai/gptscript/pkg/config" - "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/gptscript" - "github.com/gptscript-ai/gptscript/pkg/repos/runtimes" "github.com/spf13/cobra" ) @@ -30,23 +27,15 @@ func (c *Show) Run(cmd *cobra.Command, args []string) error { return err } - cfg, err := config.ReadCLIConfig(c.root.ConfigFile) + gptScript, err := gptscript.New(cmd.Context(), opts) if err != nil { - return fmt.Errorf("failed to read CLI config: %w", err) - } - - opts = gptscript.Complete(opts) - if opts.Runner.RuntimeManager == nil { - opts.Runner.RuntimeManager = runtimes.Default(opts.Cache.CacheDir) - } - - if err = opts.Runner.RuntimeManager.SetUpCredentialHelpers(cmd.Context(), cfg); err != nil { return err } + defer gptScript.Close(true) - store, err := credentials.NewStore(cfg, opts.Runner.RuntimeManager, opts.CredentialContexts, opts.Cache.CacheDir) + store, err := gptScript.CredentialStoreFactory.NewStore(gptScript.DefaultCredentialContexts) if err != nil { - return fmt.Errorf("failed to get credentials store: %w", err) + return err } cred, exists, err := store.Get(cmd.Context(), args[0]) diff --git a/pkg/cli/eval.go b/pkg/cli/eval.go index 2cd4b1b5..4afdf112 100644 --- a/pkg/cli/eval.go +++ b/pkg/cli/eval.go @@ -10,6 +10,7 @@ import ( "github.com/gptscript-ai/gptscript/pkg/gptscript" "github.com/gptscript-ai/gptscript/pkg/input" "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/runner" "github.com/gptscript-ai/gptscript/pkg/types" "github.com/spf13/cobra" ) @@ -56,13 +57,13 @@ func (e *Eval) Run(cmd *cobra.Command, args []string) error { return err } - runner, err := gptscript.New(cmd.Context(), opts) + g, err := gptscript.New(cmd.Context(), opts) if err != nil { return err } prg, err := loader.ProgramFromSource(cmd.Context(), tool.String(), "", loader.Options{ - Cache: runner.Cache, + Cache: g.Cache, }) if err != nil { return err @@ -74,12 +75,14 @@ func (e *Eval) Run(cmd *cobra.Command, args []string) error { } if e.Chat { - return chat.Start(cmd.Context(), nil, runner, func() (types.Program, error) { - return prg, nil + return chat.Start(cmd.Context(), nil, g, func() (types.Program, error) { + return loader.ProgramFromSource(cmd.Context(), tool.String(), "", loader.Options{ + Cache: g.Cache, + }) }, os.Environ(), toolInput, "") } - toolOutput, err := runner.Run(cmd.Context(), prg, opts.Env, toolInput) + toolOutput, err := g.Run(cmd.Context(), prg, opts.Env, toolInput, runner.RunOptions{}) if err != nil { return err } diff --git a/pkg/cli/fmt.go b/pkg/cli/fmt.go index 72696756..8e669349 100644 --- a/pkg/cli/fmt.go +++ b/pkg/cli/fmt.go @@ -43,9 +43,9 @@ func (e *Fmt) Run(_ *cobra.Command, args []string) error { } if e.Write && loc != "" { - return os.WriteFile(loc, []byte(doc.String()), 0644) + return os.WriteFile(loc, []byte(doc.Print()), 0644) } - fmt.Print(doc.String()) + fmt.Print(doc.Print()) return nil } diff --git a/pkg/cli/gptscript.go b/pkg/cli/gptscript.go index 66719adc..b5a823b2 100644 --- a/pkg/cli/gptscript.go +++ b/pkg/cli/gptscript.go @@ -14,7 +14,6 @@ import ( "github.com/fatih/color" "github.com/gptscript-ai/cmd" gptscript2 "github.com/gptscript-ai/go-gptscript" - "github.com/gptscript-ai/gptscript/pkg/assemble" "github.com/gptscript-ai/gptscript/pkg/auth" "github.com/gptscript-ai/gptscript/pkg/builtin" "github.com/gptscript-ai/gptscript/pkg/cache" @@ -47,6 +46,7 @@ type GPTScript struct { CacheOptions OpenAIOptions DisplayOptions + SystemToolsDir string `usage:"Directory that contains system managed tool for which GPTScript will not manage the runtime"` Color *bool `usage:"Use color in output (default true)" default:"true"` Confirm bool `usage:"Prompt before running potentially dangerous commands"` Debug bool `usage:"Enable debug logging"` @@ -57,7 +57,6 @@ type GPTScript struct { // Input should not be using GPTSCRIPT_INPUT env var because that is the same value that is set in tool executions Input string `usage:"Read input from a file (\"-\" for stdin)" short:"f" env:"GPTSCRIPT_INPUT_FILE"` SubTool string `usage:"Use tool of this name, not the first tool in file" local:"true"` - Assemble bool `usage:"Assemble tool to a single artifact, saved to --output" hidden:"true" local:"true"` ListModels bool `usage:"List the models available and exit" local:"true"` ListTools bool `usage:"List built-in tools and exit" local:"true"` ListenAddress string `usage:"Server listen address" default:"127.0.0.1:0" hidden:"true"` @@ -146,6 +145,7 @@ func (r *GPTScript) NewGPTScriptOpts() (gptscript.Options, error) { Workspace: r.Workspace, DisablePromptServer: r.UI, DefaultModelProvider: r.DefaultModelProvider, + SystemToolsDir: r.SystemToolsDir, } if r.Confirm { @@ -215,7 +215,7 @@ func (r *GPTScript) listTools(ctx context.Context, gptScript *gptscript.GPTScrip // Don't print instructions tool.Instructions = "" - lines = append(lines, tool.String()) + lines = append(lines, tool.Print()) } fmt.Println(strings.Join(lines, "\n---\n")) return nil @@ -274,7 +274,10 @@ func (r *GPTScript) listModels(ctx context.Context, gptScript *gptscript.GPTScri if err != nil { return err } - fmt.Println(strings.Join(models, "\n")) + + for _, model := range models { + fmt.Println(model.ID) + } return nil } @@ -363,7 +366,7 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { // If the file is external, then set the SCRIPTS_PATH to the current working directory. Otherwise, // set it to the directory of the script and set the file to the base. - if !(strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "github.com")) { + if !strings.HasPrefix(file, "http://") && !strings.HasPrefix(file, "https://") && !strings.HasPrefix(file, "github.com") { absPathToScript, err := filepath.Abs(file) if err != nil { return fmt.Errorf("cannot determine absolute path to script %s: %v", file, err) @@ -434,20 +437,6 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { return cmd.Help() } - if r.Assemble { - var out io.Writer = os.Stdout - if r.Output != "" && r.Output != "-" { - f, err := os.Create(r.Output) - if err != nil { - return fmt.Errorf("opening %s: %w", r.Output, err) - } - defer f.Close() - out = f - } - - return assemble.Assemble(prg, out) - } - toolInput, err := input.FromCLI(r.Input, args) if err != nil { return err @@ -464,7 +453,7 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { // This chat in a stateless mode if r.SaveChatStateFile == "-" || r.SaveChatStateFile == "stdout" { - resp, err := gptScript.Chat(cmd.Context(), chatState, prg, gptOpt.Env, toolInput) + resp, err := gptScript.Chat(cmd.Context(), chatState, prg, gptOpt.Env, toolInput, runner.RunOptions{}) if err != nil { return err } @@ -480,8 +469,8 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { // Don't use cmd.Context() because then sigint will cancel everything return tui.Run(context.Background(), args[0], tui.RunOptions{ ClientOpts: &gptscript2.GlobalOptions{ - OpenAIAPIKey: r.OpenAIOptions.APIKey, - OpenAIBaseURL: r.OpenAIOptions.BaseURL, + OpenAIAPIKey: r.APIKey, + OpenAIBaseURL: r.BaseURL, DefaultModel: r.DefaultModel, DefaultModelProvider: r.DefaultModelProvider, }, @@ -489,7 +478,6 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { DisableCache: r.DisableCache, CredentialOverrides: r.CredentialOverride, Input: toolInput, - CacheDir: r.CacheDir, SubTool: r.SubTool, Workspace: r.Workspace, SaveChatStateFile: r.SaveChatStateFile, @@ -507,7 +495,7 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) { gptScript.ExtraEnv = nil } - s, err := gptScript.Run(cmd.Context(), prg, gptOpt.Env, toolInput) + s, err := gptScript.Run(cmd.Context(), prg, gptOpt.Env, toolInput, runner.RunOptions{}) if err != nil { return err } diff --git a/pkg/cli/main.go b/pkg/cli/main.go index b607281b..33048e0e 100644 --- a/pkg/cli/main.go +++ b/pkg/cli/main.go @@ -2,24 +2,36 @@ package cli import ( "context" + "fmt" "os" "os/signal" "github.com/gptscript-ai/cmd" "github.com/gptscript-ai/gptscript/pkg/daemon" "github.com/gptscript-ai/gptscript/pkg/mvl" + "github.com/nanobot-ai/nanobot/pkg/supervise" ) func Main() { - if len(os.Args) > 2 && os.Args[1] == "sys.daemon" { - if os.Getenv("GPTSCRIPT_DEBUG") == "true" { - mvl.SetDebug() + if len(os.Args) > 2 { + if os.Args[1] == "sys.daemon" { + if os.Getenv("GPTSCRIPT_DEBUG") == "true" { + mvl.SetDebug() + } + if err := daemon.SysDaemon(); err != nil { + log.Debugf("failed running daemon: %v", err) + } + os.Exit(0) } - if err := daemon.SysDaemon(); err != nil { - log.Debugf("failed running daemon: %v", err) + if os.Args[1] == "_exec" { + if err := supervise.Daemon(); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "failed running _exec: %v\n", err) + os.Exit(1) + } + os.Exit(0) } - os.Exit(0) } + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() cmd.MainCtx(ctx, New()) diff --git a/pkg/cli/sdk_server.go b/pkg/cli/sdk_server.go index c9cf480f..42f0f949 100644 --- a/pkg/cli/sdk_server.go +++ b/pkg/cli/sdk_server.go @@ -11,6 +11,8 @@ import ( type SDKServer struct { *GPTScript + DatasetTool string `usage:"Tool to use for datasets"` + WorkspaceTool string `usage:"Tool to use for workspace"` } func (c *SDKServer) Customize(cmd *cobra.Command) { @@ -37,5 +39,7 @@ func (c *SDKServer) Run(cmd *cobra.Command, _ []string) error { Options: opts, ListenAddress: c.ListenAddress, Debug: c.Debug, + DatasetTool: c.DatasetTool, + WorkspaceTool: c.WorkspaceTool, }) } diff --git a/pkg/config/cliconfig.go b/pkg/config/cliconfig.go index 7a82b58a..d7944d8e 100644 --- a/pkg/config/cliconfig.go +++ b/pkg/config/cliconfig.go @@ -3,16 +3,15 @@ package config import ( "encoding/base64" "encoding/json" - "errors" "fmt" "os" "runtime" - "slices" "strings" "sync" "github.com/adrg/xdg" "github.com/docker/cli/cli/config/types" + "github.com/gptscript-ai/gptscript/pkg/mvl" ) const ( @@ -21,27 +20,14 @@ const ( SecretserviceCredHelper = "secretservice" PassCredHelper = "pass" FileCredHelper = "file" - SqliteCredHelper = "sqlite" - - GPTScriptHelperPrefix = "gptscript-credential-" ) var ( - darwinHelpers = []string{OsxkeychainCredHelper, FileCredHelper, SqliteCredHelper} - windowsHelpers = []string{WincredCredHelper, FileCredHelper} - linuxHelpers = []string{SecretserviceCredHelper, PassCredHelper, FileCredHelper, SqliteCredHelper} + // Helpers is a list of all supported credential helpers from github.com/gptscript-ai/gptscript-credential-helpers + Helpers = []string{WincredCredHelper, OsxkeychainCredHelper, SecretserviceCredHelper, PassCredHelper} + log = mvl.Package() ) -func listAsString(helpers []string) string { - if len(helpers) == 0 { - return "" - } else if len(helpers) == 1 { - return helpers[0] - } - - return strings.Join(helpers[:len(helpers)-1], ", ") + " or " + helpers[len(helpers)-1] -} - type AuthConfig types.AuthConfig func (a AuthConfig) MarshalJSON() ([]byte, error) { @@ -73,9 +59,8 @@ func (a *AuthConfig) UnmarshalJSON(data []byte) error { type CLIConfig struct { Auths map[string]AuthConfig `json:"auths,omitempty"` CredentialsStore string `json:"credsStore,omitempty"` - GatewayURL string `json:"gatewayURL,omitempty"` - Integrations map[string]string `json:"integrations,omitempty"` + raw []byte auths map[string]types.AuthConfig authsLock *sync.Mutex location string @@ -102,13 +87,25 @@ func (c *CLIConfig) Save() error { } if c.auths != nil { - c.Auths = map[string]AuthConfig{} + c.Auths = make(map[string]AuthConfig, len(c.auths)) for k, v := range c.auths { - c.Auths[k] = (AuthConfig)(v) + c.Auths[k] = AuthConfig(v) } c.auths = nil } - data, err := json.Marshal(c) + + // This is to not overwrite additional fields that might be the config file + out := map[string]any{} + if len(c.raw) > 0 { + err := json.Unmarshal(c.raw, &out) + if err != nil { + return err + } + } + out["auths"] = c.Auths + out["credsStore"] = c.CredentialsStore + + data, err := json.Marshal(out) if err != nil { return err } @@ -121,13 +118,21 @@ func (c *CLIConfig) GetAuthConfigs() map[string]types.AuthConfig { defer c.authsLock.Unlock() } + if err := c.readFileIntoConfig(c.location); err != nil { + // This is implementing an interface, so we can't return this error. + log.Warnf("Failed to read config file: %v", err) + } + if c.auths == nil { - c.auths = map[string]types.AuthConfig{} - for k, v := range c.Auths { - authConfig := (types.AuthConfig)(v) - c.auths[k] = authConfig - } + c.auths = make(map[string]types.AuthConfig, len(c.Auths)) + } + + // Assume that whatever was pulled from the file is more recent. + // The docker creds framework will save the file after creating or updating a credential. + for k, v := range c.Auths { + c.auths[k] = types.AuthConfig(v) } + return c.auths } @@ -147,16 +152,17 @@ func ReadCLIConfig(gptscriptConfigFile string) (*CLIConfig, error) { } } - data, err := readFile(gptscriptConfigFile) - if err != nil { - return nil, err - } result := &CLIConfig{ authsLock: &sync.Mutex{}, location: gptscriptConfigFile, } - if err := json.Unmarshal(data, result); err != nil { - return nil, fmt.Errorf("failed to unmarshal %s: %v", gptscriptConfigFile, err) + + if err := result.readFileIntoConfig(gptscriptConfigFile); err != nil { + return nil, err + } + + if store := os.Getenv("GPTSCRIPT_CREDENTIAL_STORE"); store != "" { + result.CredentialsStore = store } if result.CredentialsStore == "" { @@ -165,23 +171,6 @@ func ReadCLIConfig(gptscriptConfigFile string) (*CLIConfig, error) { } } - if !isValidCredentialHelper(result.CredentialsStore) { - errMsg := fmt.Sprintf("invalid credential store '%s'", result.CredentialsStore) - switch runtime.GOOS { - case "darwin": - errMsg += fmt.Sprintf(" (use %s)", listAsString(darwinHelpers)) - case "windows": - errMsg += fmt.Sprintf(" (use %s)", listAsString(windowsHelpers)) - case "linux": - errMsg += fmt.Sprintf(" (use %s)", listAsString(linuxHelpers)) - default: - errMsg += " (use file)" - } - errMsg += fmt.Sprintf("\nPlease edit your config file at %s to fix this.", result.location) - - return nil, errors.New(errMsg) - } - return result, nil } @@ -197,26 +186,18 @@ func (c *CLIConfig) setDefaultCredentialsStore() error { return c.Save() } -func isValidCredentialHelper(helper string) bool { - switch runtime.GOOS { - case "darwin": - return slices.Contains(darwinHelpers, helper) - case "windows": - return slices.Contains(windowsHelpers, helper) - case "linux": - return slices.Contains(linuxHelpers, helper) - default: - return helper == FileCredHelper - } -} - -func readFile(path string) ([]byte, error) { +func (c *CLIConfig) readFileIntoConfig(path string) error { data, err := os.ReadFile(path) if os.IsNotExist(err) { - return []byte("{}"), nil + return nil } else if err != nil { - return nil, fmt.Errorf("failed to read user config %s: %w", path, err) + return fmt.Errorf("failed to read user config %s: %w", path, err) + } + + c.raw = data + if err := json.Unmarshal(data, c); err != nil { + return fmt.Errorf("failed to unmarshal %s: %v", path, err) } - return data, nil + return nil } diff --git a/pkg/context/context.go b/pkg/context/context.go index 0169d0e0..31474f6c 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -46,14 +46,3 @@ func GetLogger(ctx context.Context) mvl.Logger { return l } - -type envKey struct{} - -func WithEnv(ctx context.Context, env []string) context.Context { - return context.WithValue(ctx, envKey{}, env) -} - -func GetEnv(ctx context.Context) []string { - l, _ := ctx.Value(envKey{}).([]string) - return l -} diff --git a/pkg/credentials/credential.go b/pkg/credentials/credential.go index f589a065..9d314a70 100644 --- a/pkg/credentials/credential.go +++ b/pkg/credentials/credential.go @@ -20,13 +20,16 @@ const ( ) type Credential struct { - Context string `json:"context"` - ToolName string `json:"toolName"` - Type CredentialType `json:"type"` - Env map[string]string `json:"env"` - Ephemeral bool `json:"ephemeral,omitempty"` - ExpiresAt *time.Time `json:"expiresAt"` - RefreshToken string `json:"refreshToken"` + Context string `json:"context"` + ToolName string `json:"toolName"` + Type CredentialType `json:"type"` + Env map[string]string `json:"env"` + // If the CheckParam that is stored is different from the param on the tool, + // then the credential will be re-authed as if it does not exist. + CheckParam string `json:"checkParam"` + Ephemeral bool `json:"ephemeral,omitempty"` + ExpiresAt *time.Time `json:"expiresAt"` + RefreshToken string `json:"refreshToken"` } func (c Credential) IsExpired() bool { @@ -55,13 +58,8 @@ func (c Credential) toDockerAuthConfig() (types.AuthConfig, error) { func credentialFromDockerAuthConfig(authCfg types.AuthConfig) (Credential, error) { var cred Credential if authCfg.Password != "" { - if err := json.Unmarshal([]byte(authCfg.Password), &cred); err != nil || len(cred.Env) == 0 { - // Legacy: try unmarshalling into just an env map - var env map[string]string - if err := json.Unmarshal([]byte(authCfg.Password), &env); err != nil { - return Credential{}, err - } - cred.Env = env + if err := json.Unmarshal([]byte(authCfg.Password), &cred); err != nil { + return cred, fmt.Errorf("failed to unmarshal credential: %w", err) } } @@ -87,6 +85,7 @@ func credentialFromDockerAuthConfig(authCfg types.AuthConfig) (Credential, error Context: ctx, ToolName: tool, Type: CredentialType(credType), + CheckParam: cred.CheckParam, Env: cred.Env, ExpiresAt: cred.ExpiresAt, RefreshToken: cred.RefreshToken, diff --git a/pkg/credentials/error.go b/pkg/credentials/error.go new file mode 100644 index 00000000..f3990f7c --- /dev/null +++ b/pkg/credentials/error.go @@ -0,0 +1,12 @@ +package credentials + +import ( + "strings" +) + +func IsCredentialsNotFoundError(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "credentials not found in native keychain") +} diff --git a/pkg/credentials/factory.go b/pkg/credentials/factory.go new file mode 100644 index 00000000..60f1c838 --- /dev/null +++ b/pkg/credentials/factory.go @@ -0,0 +1,109 @@ +package credentials + +import ( + "context" + "strings" + + "github.com/docker/docker-credential-helpers/client" + "github.com/gptscript-ai/gptscript/pkg/config" + "github.com/gptscript-ai/gptscript/pkg/types" +) + +type ProgramLoaderRunner interface { + Load(ctx context.Context, toolName string) (prg types.Program, err error) + Run(ctx context.Context, prg types.Program, input string) (output string, err error) +} + +func NewFactory(ctx context.Context, cfg *config.CLIConfig, overrides []string, plr ProgramLoaderRunner) (StoreFactory, error) { + creds, err := ParseCredentialOverrides(overrides) + if err != nil { + return StoreFactory{}, err + } + + overrideMap := make(map[string]map[string]map[string]string) + for k, v := range creds { + contextName, toolName, ok := strings.Cut(k, ctxSeparator) + if !ok { + continue + } + toolMap, ok := overrideMap[contextName] + if !ok { + toolMap = make(map[string]map[string]string) + } + toolMap[toolName] = v + overrideMap[contextName] = toolMap + } + + toolName := translateToolName(cfg.CredentialsStore) + if toolName == config.FileCredHelper { + return StoreFactory{ + file: true, + cfg: cfg, + overrides: overrideMap, + }, nil + } + + prg, err := plr.Load(ctx, toolName) + if err != nil { + return StoreFactory{}, err + } + + return StoreFactory{ + ctx: ctx, + prg: prg, + runner: plr, + cfg: cfg, + overrides: overrideMap, + }, nil +} + +type StoreFactory struct { + ctx context.Context + prg types.Program + file bool + runner ProgramLoaderRunner + cfg *config.CLIConfig + // That's a lot of maps: context -> toolName -> key -> value + overrides map[string]map[string]map[string]string +} + +func (s *StoreFactory) NewStore(credCtxs []string) (CredentialStore, error) { + if err := validateCredentialCtx(credCtxs); err != nil { + return nil, err + } + if s.file { + return &withOverride{ + target: &Store{ + credCtxs: credCtxs, + cfg: s.cfg, + }, + overrides: s.overrides, + credContext: credCtxs, + }, nil + } + return &withOverride{ + target: &Store{ + credCtxs: credCtxs, + cfg: s.cfg, + program: s.program, + }, + overrides: s.overrides, + credContext: credCtxs, + }, nil +} + +func (s *StoreFactory) program(args ...string) client.Program { + return &runnerProgram{ + factory: s, + action: args[0], + } +} + +func translateToolName(toolName string) string { + for _, helper := range config.Helpers { + if helper == toolName { + return "github.com/gptscript-ai/gptscript-credential-helpers/" + toolName + "/cmd" + } + } + return toolName +} diff --git a/pkg/credentials/helper.go b/pkg/credentials/helper.go deleted file mode 100644 index e5cd34f6..00000000 --- a/pkg/credentials/helper.go +++ /dev/null @@ -1,112 +0,0 @@ -package credentials - -import ( - "errors" - "net/url" - "regexp" - "strings" - - "github.com/docker/cli/cli/config/credentials" - "github.com/docker/cli/cli/config/types" - "github.com/docker/docker-credential-helpers/client" - credentials2 "github.com/docker/docker-credential-helpers/credentials" - "github.com/gptscript-ai/gptscript/pkg/config" -) - -func NewHelper(c *config.CLIConfig, helper string) (credentials.Store, error) { - return &HelperStore{ - file: credentials.NewFileStore(c), - program: client.NewShellProgramFunc(helper), - }, nil -} - -type HelperStore struct { - file credentials.Store - program client.ProgramFunc -} - -func (h *HelperStore) Erase(serverAddress string) error { - var errs []error - if err := client.Erase(h.program, serverAddress); err != nil { - errs = append(errs, err) - } - if err := h.file.Erase(serverAddress); err != nil { - errs = append(errs, err) - } - return errors.Join(errs...) -} - -func (h *HelperStore) Get(serverAddress string) (types.AuthConfig, error) { - creds, err := client.Get(h.program, serverAddress) - if credentials2.IsErrCredentialsNotFound(err) { - return h.file.Get(serverAddress) - } else if err != nil { - return types.AuthConfig{}, err - } - return types.AuthConfig{ - Username: creds.Username, - Password: creds.Secret, - ServerAddress: serverAddress, - }, nil -} - -func (h *HelperStore) GetAll() (map[string]types.AuthConfig, error) { - result := map[string]types.AuthConfig{} - - serverAddresses, err := client.List(h.program) - if err != nil { - return nil, err - } - - newCredAddresses := make(map[string]string, len(serverAddresses)) - for serverAddress, val := range serverAddresses { - // If the serverAddress contains a port, we need to put it back in the right spot. - // For some reason, even when a credential is stored properly as http://hostname:8080///credctx, - // the list function will return http://hostname///credctx:8080. This is something wrong - // with macOS's built-in libraries. So we need to fix it here. - toolName, ctx, err := toolNameAndCtxFromAddress(serverAddress) - if err != nil { - return nil, err - } - - contextPieces := strings.Split(ctx, ":") - if len(contextPieces) > 1 { - possiblePortNumber := contextPieces[len(contextPieces)-1] - if regexp.MustCompile(`^\d+$`).MatchString(possiblePortNumber) { - // port number confirmed - toolURL, err := url.Parse(toolName) - if err != nil { - return nil, err - } - - // Save the path so we can put it back after removing it. - path := toolURL.Path - toolURL.Path = "" - - toolName = toolURL.String() + ":" + possiblePortNumber + path - ctx = strings.TrimSuffix(ctx, ":"+possiblePortNumber) - } - } - - newCredAddresses[toolNameWithCtx(toolName, ctx)] = val - delete(serverAddresses, serverAddress) - } - - for serverAddress := range newCredAddresses { - ac, err := h.Get(serverAddress) - if err != nil { - return nil, err - } - result[serverAddress] = ac - } - - return result, nil -} - -func (h *HelperStore) Store(authConfig types.AuthConfig) error { - return client.Store(h.program, &credentials2.Credentials{ - ServerURL: authConfig.ServerAddress, - Username: authConfig.Username, - Secret: authConfig.Password, - }) -} diff --git a/pkg/credentials/noop.go b/pkg/credentials/noop.go index 3a13b907..540d80aa 100644 --- a/pkg/credentials/noop.go +++ b/pkg/credentials/noop.go @@ -1,6 +1,8 @@ package credentials -import "context" +import ( + "context" +) type NoopStore struct{} @@ -23,3 +25,7 @@ func (s NoopStore) Remove(context.Context, string) error { func (s NoopStore) List(context.Context) ([]Credential, error) { return nil, nil } + +func (s NoopStore) RecreateAll(context.Context) error { + return nil +} diff --git a/pkg/credentials/overrides.go b/pkg/credentials/overrides.go new file mode 100644 index 00000000..747909d7 --- /dev/null +++ b/pkg/credentials/overrides.go @@ -0,0 +1,153 @@ +package credentials + +import ( + "context" + "fmt" + "maps" + "os" + "strings" +) + +// ParseCredentialOverrides parses a string of credential overrides that the user provided as a command line arg. +// The format of credential overrides can be one of two things: +// cred1:ENV1,ENV2 (direct mapping of environment variables) +// cred1:ENV1=VALUE1,ENV2=VALUE2 (key-value pairs) +// +// This function turns it into a map[string]map[string]string like this: +// +// { +// "cred1": { +// "ENV1": "VALUE1", +// "ENV2": "VALUE2", +// } +// } +func ParseCredentialOverrides(overrides []string) (map[string]map[string]string, error) { + credentialOverrides := make(map[string]map[string]string) + + for _, o := range overrides { + credName, envs, found := strings.Cut(o, ":") + if !found { + return nil, fmt.Errorf("invalid credential override: %s", o) + } + envMap, ok := credentialOverrides[credName] + if !ok { + envMap = make(map[string]string) + } + for _, env := range strings.Split(envs, ",") { + for _, env := range strings.Split(env, "|") { + key, value, found := strings.Cut(env, "=") + if !found { + // User just passed an env var name as the key, so look up the value. + value = os.Getenv(key) + } + envMap[key] = value + } + } + credentialOverrides[credName] = envMap + } + + return credentialOverrides, nil +} + +type withOverride struct { + target CredentialStore + credContext []string + overrides map[string]map[string]map[string]string +} + +func (w withOverride) Get(ctx context.Context, toolName string) (*Credential, bool, error) { + for _, credCtx := range w.credContext { + overrides, ok := w.overrides[credCtx] + if !ok { + continue + } + override, ok := overrides[toolName] + if !ok { + continue + } + + return &Credential{ + Context: credCtx, + ToolName: toolName, + Type: CredentialTypeTool, + Env: maps.Clone(override), + }, true, nil + } + + return w.target.Get(ctx, toolName) +} + +func (w withOverride) Add(ctx context.Context, cred Credential) error { + for _, credCtx := range w.credContext { + if override, ok := w.overrides[credCtx]; ok { + if _, ok := override[cred.ToolName]; ok { + return fmt.Errorf("cannot add credential with context %q and tool %q because it is statically configure", cred.Context, cred.ToolName) + } + } + } + return w.target.Add(ctx, cred) +} + +func (w withOverride) Refresh(ctx context.Context, cred Credential) error { + if override, ok := w.overrides[cred.Context]; ok { + if _, ok := override[cred.ToolName]; ok { + return nil + } + } + return w.target.Refresh(ctx, cred) +} + +func (w withOverride) Remove(ctx context.Context, toolName string) error { + for _, credCtx := range w.credContext { + if override, ok := w.overrides[credCtx]; ok { + if _, ok := override[toolName]; ok { + return fmt.Errorf("cannot remove credential with context %q and tool %q because it is statically configure", credCtx, toolName) + } + } + } + return w.target.Remove(ctx, toolName) +} + +func (w withOverride) List(ctx context.Context) ([]Credential, error) { + creds, err := w.target.List(ctx) + if err != nil { + return nil, err + } + + added := make(map[string]map[string]bool) + for i, cred := range creds { + if override, ok := w.overrides[cred.Context]; ok { + if _, ok := override[cred.ToolName]; ok { + creds[i].Type = CredentialTypeTool + creds[i].Env = maps.Clone(override[cred.ToolName]) + } + } + tools, ok := added[cred.Context] + if !ok { + tools = make(map[string]bool) + } + tools[cred.ToolName] = true + added[cred.Context] = tools + } + + for _, credCtx := range w.credContext { + tools := w.overrides[credCtx] + for toolName := range tools { + if _, ok := added[credCtx][toolName]; ok { + continue + } + creds = append(creds, Credential{ + Context: credCtx, + ToolName: toolName, + Type: CredentialTypeTool, + Env: maps.Clone(tools[toolName]), + }) + } + } + + return creds, nil +} + +func (w withOverride) RecreateAll(ctx context.Context) error { + return w.target.RecreateAll(ctx) +} diff --git a/pkg/credentials/runnerprogram.go b/pkg/credentials/runnerprogram.go new file mode 100644 index 00000000..4ae123a0 --- /dev/null +++ b/pkg/credentials/runnerprogram.go @@ -0,0 +1,29 @@ +package credentials + +import ( + "io" +) + +type runnerProgram struct { + factory *StoreFactory + action string + output string + err error +} + +func (r *runnerProgram) Output() ([]byte, error) { + return []byte(r.output), r.err +} + +func (r *runnerProgram) Input(in io.Reader) { + input, err := io.ReadAll(in) + if err != nil { + r.err = err + return + } + + prg := r.factory.prg + prg.EntryToolID = prg.ToolSet[prg.EntryToolID].LocalTools[r.action] + + r.output, r.err = r.factory.runner.Run(r.factory.ctx, prg, string(input)) +} diff --git a/pkg/credentials/store.go b/pkg/credentials/store.go index 9827b147..6e5d24ca 100644 --- a/pkg/credentials/store.go +++ b/pkg/credentials/store.go @@ -3,14 +3,13 @@ package credentials import ( "context" "fmt" - "path/filepath" "regexp" "slices" - "strings" + "sync" "github.com/docker/cli/cli/config/credentials" "github.com/docker/cli/cli/config/types" - credentials2 "github.com/docker/docker-credential-helpers/credentials" + "github.com/docker/docker-credential-helpers/client" "github.com/gptscript-ai/gptscript/pkg/config" "golang.org/x/exp/maps" ) @@ -20,43 +19,31 @@ const ( AllCredentialContexts = "*" ) -type CredentialBuilder interface { - EnsureCredentialHelpers(ctx context.Context) error -} - type CredentialStore interface { Get(ctx context.Context, toolName string) (*Credential, bool, error) Add(ctx context.Context, cred Credential) error Refresh(ctx context.Context, cred Credential) error Remove(ctx context.Context, toolName string) error List(ctx context.Context) ([]Credential, error) + RecreateAll(ctx context.Context) error } type Store struct { - credCtxs []string - credBuilder CredentialBuilder - credHelperDirs CredentialHelperDirs - cfg *config.CLIConfig + credCtxs []string + cfg *config.CLIConfig + program client.ProgramFunc + recreateAllLock sync.RWMutex } -func NewStore(cfg *config.CLIConfig, credentialBuilder CredentialBuilder, credCtxs []string, cacheDir string) (CredentialStore, error) { - if err := validateCredentialCtx(credCtxs); err != nil { - return nil, err - } - return Store{ - credCtxs: credCtxs, - credBuilder: credentialBuilder, - credHelperDirs: GetCredentialHelperDirs(cacheDir, cfg.CredentialsStore), - cfg: cfg, - }, nil -} +func (s *Store) Get(_ context.Context, toolName string) (*Credential, bool, error) { + s.recreateAllLock.RLock() + defer s.recreateAllLock.RUnlock() -func (s Store) Get(ctx context.Context, toolName string) (*Credential, bool, error) { - if first(s.credCtxs) == AllCredentialContexts { + if len(s.credCtxs) > 0 && s.credCtxs[0] == AllCredentialContexts { return nil, false, fmt.Errorf("cannot get a credential with context %q", AllCredentialContexts) } - store, err := s.getStore(ctx) + store, err := s.getStore() if err != nil { return nil, false, err } @@ -68,7 +55,7 @@ func (s Store) Get(ctx context.Context, toolName string) (*Credential, bool, err for _, c := range s.credCtxs { auth, err := store.Get(toolNameWithCtx(toolName, c)) if err != nil { - if credentials2.IsErrCredentialsNotFound(err) { + if IsCredentialsNotFoundError(err) { continue } return nil, false, err @@ -99,14 +86,17 @@ func (s Store) Get(ctx context.Context, toolName string) (*Credential, bool, err // Add adds a new credential to the credential store. // Any context set on the credential object will be overwritten with the first context of the credential store. -func (s Store) Add(ctx context.Context, cred Credential) error { +func (s *Store) Add(_ context.Context, cred Credential) error { + s.recreateAllLock.RLock() + defer s.recreateAllLock.RUnlock() + first := first(s.credCtxs) if first == AllCredentialContexts { return fmt.Errorf("cannot add a credential with context %q", AllCredentialContexts) } cred.Context = first - store, err := s.getStore(ctx) + store, err := s.getStore() if err != nil { return err } @@ -118,12 +108,15 @@ func (s Store) Add(ctx context.Context, cred Credential) error { } // Refresh updates an existing credential in the credential store. -func (s Store) Refresh(ctx context.Context, cred Credential) error { +func (s *Store) Refresh(_ context.Context, cred Credential) error { + s.recreateAllLock.RLock() + defer s.recreateAllLock.RUnlock() + if !slices.Contains(s.credCtxs, cred.Context) { return fmt.Errorf("context %q not in list of valid contexts for this credential store", cred.Context) } - store, err := s.getStore(ctx) + store, err := s.getStore() if err != nil { return err } @@ -134,13 +127,16 @@ func (s Store) Refresh(ctx context.Context, cred Credential) error { return store.Store(auth) } -func (s Store) Remove(ctx context.Context, toolName string) error { +func (s *Store) Remove(_ context.Context, toolName string) error { + s.recreateAllLock.RLock() + defer s.recreateAllLock.RUnlock() + first := first(s.credCtxs) if len(s.credCtxs) > 1 || first == AllCredentialContexts { return fmt.Errorf("error: credential deletion is not supported when multiple credential contexts are provided") } - store, err := s.getStore(ctx) + store, err := s.getStore() if err != nil { return err } @@ -148,8 +144,11 @@ func (s Store) Remove(ctx context.Context, toolName string) error { return store.Erase(toolNameWithCtx(toolName, first)) } -func (s Store) List(ctx context.Context) ([]Credential, error) { - store, err := s.getStore(ctx) +func (s *Store) List(_ context.Context) ([]Credential, error) { + s.recreateAllLock.RLock() + defer s.recreateAllLock.RUnlock() + + store, err := s.getStore() if err != nil { return nil, err } @@ -158,61 +157,124 @@ func (s Store) List(ctx context.Context) ([]Credential, error) { return nil, err } - credsByContext := make(map[string][]Credential) - allCreds := make([]Credential, 0) - for serverAddress, authCfg := range list { - if authCfg.ServerAddress == "" { - authCfg.ServerAddress = serverAddress // Not sure why we have to do this, but we do. + if len(s.credCtxs) > 0 && s.credCtxs[0] == AllCredentialContexts { + allCreds := make([]Credential, 0, len(list)) + for serverAddress := range list { + ac, err := store.Get(serverAddress) + if err != nil { + return nil, err + } + ac.ServerAddress = serverAddress + + cred, err := credentialFromDockerAuthConfig(ac) + if err != nil { + return nil, err + } + allCreds = append(allCreds, cred) } - c, err := credentialFromDockerAuthConfig(authCfg) + return allCreds, nil + } + + serverAddressesByContext := make(map[string][]string) + for serverAddress := range list { + _, ctx, err := toolNameAndCtxFromAddress(serverAddress) if err != nil { return nil, err } - allCreds = append(allCreds, c) - - if credsByContext[c.Context] == nil { - credsByContext[c.Context] = []Credential{c} + if serverAddressesByContext[ctx] == nil { + serverAddressesByContext[ctx] = []string{serverAddress} } else { - credsByContext[c.Context] = append(credsByContext[c.Context], c) + serverAddressesByContext[ctx] = append(serverAddressesByContext[ctx], serverAddress) } } - if first(s.credCtxs) == AllCredentialContexts { - return allCreds, nil - } - // Go through the contexts in reverse order so that higher priority contexts override lower ones. credsByName := make(map[string]Credential) for i := len(s.credCtxs) - 1; i >= 0; i-- { - for _, c := range credsByContext[s.credCtxs[i]] { - credsByName[c.ToolName] = c + for _, serverAddress := range serverAddressesByContext[s.credCtxs[i]] { + ac, err := store.Get(serverAddress) + if err != nil { + return nil, err + } + ac.ServerAddress = serverAddress + + cred, err := credentialFromDockerAuthConfig(ac) + if err != nil { + return nil, err + } + + toolName, _, err := toolNameAndCtxFromAddress(serverAddress) + if err != nil { + return nil, err + } + + credsByName[toolName] = cred } } return maps.Values(credsByName), nil } -func (s *Store) getStore(ctx context.Context) (credentials.Store, error) { - return s.getStoreByHelper(ctx, config.GPTScriptHelperPrefix+s.cfg.CredentialsStore) -} +func (s *Store) RecreateAll(_ context.Context) error { + store, err := s.getStore() + if err != nil { + return err + } -func (s *Store) getStoreByHelper(ctx context.Context, helper string) (credentials.Store, error) { - if helper == "" || helper == config.GPTScriptHelperPrefix+config.FileCredHelper { - return credentials.NewFileStore(s.cfg), nil + // New credentials might be created after our GetAll, but they will be created with the current encryption configuration, + // so it's okay that they are skipped by this function. + s.recreateAllLock.Lock() + all, err := store.GetAll() + s.recreateAllLock.Unlock() + if err != nil { + return err } - // If the helper is referencing one of the credential helper programs, then reference the full path. - if strings.HasPrefix(helper, "gptscript-credential-") { - if err := s.credBuilder.EnsureCredentialHelpers(ctx); err != nil { - return nil, err + // Loop through and recreate each individual credential. + for serverAddress := range all { + if err := s.recreateCredential(store, serverAddress); err != nil { + return err + } + } + + return nil +} + +func (s *Store) recreateCredential(store credentials.Store, serverAddress string) error { + s.recreateAllLock.Lock() + defer s.recreateAllLock.Unlock() + + authConfig, err := store.Get(serverAddress) + if err != nil { + if IsCredentialsNotFoundError(err) { + // This can happen if the credential was deleted between the GetAll and the Get by another thread. + return nil } + return err + } - helper = filepath.Join(s.credHelperDirs.BinDir, helper) + if err := store.Erase(serverAddress); err != nil { + return err } - return NewHelper(s.cfg, helper) + if err := store.Store(authConfig); err != nil { + return err + } + + return nil +} + +func (s *Store) getStore() (credentials.Store, error) { + if s.program != nil { + return &toolCredentialStore{ + file: credentials.NewFileStore(s.cfg), + program: s.program, + contexts: s.credCtxs, + }, nil + } + return credentials.NewFileStore(s.cfg), nil } func validateCredentialCtx(ctxs []string) error { @@ -225,7 +287,7 @@ func validateCredentialCtx(ctxs []string) error { } // check alphanumeric - r := regexp.MustCompile("^[a-zA-Z0-9]+$") + r := regexp.MustCompile("^[-a-zA-Z0-9.]+$") for _, c := range ctxs { if !r.MatchString(c) { return fmt.Errorf("credential contexts must be alphanumeric") @@ -234,3 +296,10 @@ func validateCredentialCtx(ctxs []string) error { return nil } + +func first(s []string) string { + if len(s) == 0 { + return "" + } + return s[0] +} diff --git a/pkg/credentials/toolstore.go b/pkg/credentials/toolstore.go new file mode 100644 index 00000000..66d4d38d --- /dev/null +++ b/pkg/credentials/toolstore.go @@ -0,0 +1,154 @@ +package credentials + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "net/url" + "regexp" + "strings" + + "github.com/docker/cli/cli/config/credentials" + "github.com/docker/cli/cli/config/types" + "github.com/docker/docker-credential-helpers/client" + credentials2 "github.com/docker/docker-credential-helpers/credentials" +) + +type toolCredentialStore struct { + file credentials.Store + program client.ProgramFunc + contexts []string +} + +func (h *toolCredentialStore) Erase(serverAddress string) error { + var errs []error + if err := client.Erase(h.program, serverAddress); err != nil { + errs = append(errs, err) + } + if err := h.file.Erase(serverAddress); err != nil { + errs = append(errs, err) + } + return errors.Join(errs...) +} + +func (h *toolCredentialStore) Get(serverAddress string) (types.AuthConfig, error) { + creds, err := client.Get(h.program, serverAddress) + if IsCredentialsNotFoundError(err) { + return h.file.Get(serverAddress) + } else if err != nil { + return types.AuthConfig{}, err + } + return types.AuthConfig{ + Username: creds.Username, + Password: creds.Secret, + ServerAddress: serverAddress, + }, nil +} + +// GetAll will list all credentials in the credential store. +// It MAY (but is not required to) filter the credentials based on the contexts provided. +// This is only supported by some credential stores, while others will ignore it and return all credentials. +// The caller of this function is still required to filter the output to only include the contexts requested. +func (h *toolCredentialStore) GetAll() (map[string]types.AuthConfig, error) { + var ( + serverAddresses map[string]string + err error + ) + if len(h.contexts) == 0 { + serverAddresses, err = client.List(h.program) + } else { + serverAddresses, err = listWithContexts(h.program, h.contexts) + } + + if err != nil { + return nil, err + } + + result := make(map[string]types.AuthConfig, len(serverAddresses)) + for serverAddress, val := range serverAddresses { + // If the serverAddress contains a port, we need to put it back in the right spot. + // For some reason, even when a credential is stored properly as http://hostname:8080///credctx, + // the list function will return http://hostname///credctx:8080. This is something wrong + // with macOS's built-in libraries. So we need to fix it here. + toolName, ctx, err := toolNameAndCtxFromAddress(serverAddress) + if err != nil { + return nil, err + } + + contextPieces := strings.Split(ctx, ":") + if len(contextPieces) > 1 { + possiblePortNumber := contextPieces[len(contextPieces)-1] + if regexp.MustCompile(`^\d+$`).MatchString(possiblePortNumber) { + // port number confirmed + toolURL, err := url.Parse(toolName) + if err != nil { + return nil, err + } + + // Save the path so we can put it back after removing it. + path := toolURL.Path + toolURL.Path = "" + + toolName = toolURL.String() + ":" + possiblePortNumber + path + ctx = strings.TrimSuffix(ctx, ":"+possiblePortNumber) + } + } + + result[toolNameWithCtx(toolName, ctx)] = types.AuthConfig{ + Username: val, + ServerAddress: serverAddress, + } + } + + return result, nil +} + +func (h *toolCredentialStore) Store(authConfig types.AuthConfig) error { + return client.Store(h.program, &credentials2.Credentials{ + ServerURL: authConfig.ServerAddress, + Username: authConfig.Username, + Secret: authConfig.Password, + }) +} + +// listWithContexts is almost an exact copy of the List function in Docker's libraries, +// the only difference being that we pass the context through as input to the program. +// This will allow some credential stores, like Postgres, to do an optimized list. +func listWithContexts(program client.ProgramFunc, contexts []string) (map[string]string, error) { + cmd := program(credentials2.ActionList) + + contextsJSON, err := json.Marshal(contexts) + if err != nil { + return nil, err + } + + cmd.Input(bytes.NewReader(contextsJSON)) + out, err := cmd.Output() + if err != nil { + t := strings.TrimSpace(string(out)) + + if isValidErr := isValidCredsMessage(t); isValidErr != nil { + err = isValidErr + } + + return nil, fmt.Errorf("error listing credentials - err: %v, out: `%s`", err, t) + } + + var resp map[string]string + if err = json.NewDecoder(bytes.NewReader(out)).Decode(&resp); err != nil { + return nil, err + } + + return resp, nil +} + +func isValidCredsMessage(msg string) error { + if credentials2.IsCredentialsMissingServerURLMessage(msg) { + return credentials2.NewErrCredentialsMissingServerURL() + } + if credentials2.IsCredentialsMissingUsernameMessage(msg) { + return credentials2.NewErrCredentialsMissingUsername() + } + return nil +} diff --git a/pkg/credentials/toolstore_test.go b/pkg/credentials/toolstore_test.go new file mode 100644 index 00000000..fdbae25c --- /dev/null +++ b/pkg/credentials/toolstore_test.go @@ -0,0 +1,130 @@ +package credentials + +import ( + "encoding/json" + "fmt" + "io" + "testing" + + "github.com/docker/cli/cli/config/types" + "github.com/docker/docker-credential-helpers/client" + "github.com/docker/docker-credential-helpers/credentials" +) + +type mockProgram struct { + // mode is either "db" or "normal" + // db mode will honor contexts, normal mode will not + mode string + action string + contexts []string +} + +func (m *mockProgram) Input(in io.Reader) { + switch m.action { + case credentials.ActionList: + var contexts []string + if err := json.NewDecoder(in).Decode(&contexts); err == nil && len(contexts) > 0 { + m.contexts = contexts + } + } + // TODO: add other cases here as needed +} + +func (m *mockProgram) Output() ([]byte, error) { + switch m.action { + case credentials.ActionList: + switch m.mode { + case "db": + // Return only credentials that are in the list of contexts. + creds := make(map[string]string) + for _, context := range m.contexts { + creds[fmt.Sprintf("https://example///%s", context)] = "username" + } + return json.Marshal(creds) + case "normal": + // Return credentials in the list of contexts, plus some made up extras. + creds := make(map[string]string) + for _, context := range m.contexts { + creds[fmt.Sprintf("https://example///%s", context)] = "username" + } + creds[fmt.Sprintf("https://example///%s", "otherContext1")] = "username" + creds[fmt.Sprintf("https://example///%s", "otherContext2")] = "username" + return json.Marshal(creds) + } + } + return nil, nil +} + +func newMockProgram(t *testing.T, mode string) client.ProgramFunc { + t.Helper() + return func(args ...string) client.Program { + p := &mockProgram{ + mode: mode, + } + if len(args) > 0 { + p.action = args[0] + } + return p + } +} + +func TestGetAll(t *testing.T) { + dbProgram := newMockProgram(t, "db") + normalProgram := newMockProgram(t, "normal") + + tests := []struct { + name string + program client.ProgramFunc + wantErr bool + contexts []string + expected map[string]types.AuthConfig + }{ + {name: "db", program: dbProgram, wantErr: false, contexts: []string{"credctx"}, expected: map[string]types.AuthConfig{ + "https://example///credctx": { + Username: "username", + ServerAddress: "https://example///credctx", + }, + }}, + {name: "normal", program: normalProgram, wantErr: false, contexts: []string{"credctx"}, expected: map[string]types.AuthConfig{ + "https://example///credctx": { + Username: "username", + ServerAddress: "https://example///credctx", + }, + "https://example///otherContext1": { + Username: "username", + ServerAddress: "https://example///otherContext1", + }, + "https://example///otherContext2": { + Username: "username", + ServerAddress: "https://example///otherContext2", + }, + }}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + store := &toolCredentialStore{ + program: test.program, + contexts: test.contexts, + } + got, err := store.GetAll() + if (err != nil) != test.wantErr { + t.Errorf("GetAll() error = %v, wantErr %v", err, test.wantErr) + } + if len(got) != len(test.expected) { + t.Errorf("GetAll() got %d credentials, want %d", len(got), len(test.expected)) + } + for name, cred := range got { + if _, ok := test.expected[name]; !ok { + t.Errorf("GetAll() got unexpected credential: %s", name) + } + if got[name].Username != test.expected[name].Username { + t.Errorf("GetAll() got unexpected username for %s", cred.ServerAddress) + } + if got[name].Username != test.expected[name].Username { + t.Errorf("GetAll() got unexpected username for %s", name) + } + } + }) + } +} diff --git a/pkg/credentials/util.go b/pkg/credentials/util.go deleted file mode 100644 index 72f9eab9..00000000 --- a/pkg/credentials/util.go +++ /dev/null @@ -1,49 +0,0 @@ -package credentials - -import ( - "fmt" - "path/filepath" - - "github.com/gptscript-ai/gptscript/pkg/config" - runtimeEnv "github.com/gptscript-ai/gptscript/pkg/env" -) - -type CredentialHelperDirs struct { - RevisionFile, LastCheckedFile, BinDir string -} - -func RepoNameForCredentialStore(store string) string { - switch store { - case config.SqliteCredHelper: - return "gptscript-credential-sqlite" - default: - return "gptscript-credential-helpers" - } -} - -func GitURLForRepoName(repoName string) (string, error) { - switch repoName { - case "gptscript-credential-sqlite": - return runtimeEnv.VarOrDefault("GPTSCRIPT_CRED_SQLITE_ROOT", "https://github.com/gptscript-ai/gptscript-credential-sqlite.git"), nil - case "gptscript-credential-helpers": - return runtimeEnv.VarOrDefault("GPTSCRIPT_CRED_HELPERS_ROOT", "https://github.com/gptscript-ai/gptscript-credential-helpers.git"), nil - default: - return "", fmt.Errorf("unknown repo name: %s", repoName) - } -} - -func GetCredentialHelperDirs(cacheDir, store string) CredentialHelperDirs { - repoName := RepoNameForCredentialStore(store) - return CredentialHelperDirs{ - RevisionFile: filepath.Join(cacheDir, "repos", repoName, "revision"), - LastCheckedFile: filepath.Join(cacheDir, "repos", repoName, "last-checked"), - BinDir: filepath.Join(cacheDir, "repos", repoName, "bin"), - } -} - -func first(s []string) string { - if len(s) == 0 { - return "" - } - return s[0] -} diff --git a/pkg/engine/call.go b/pkg/engine/call.go new file mode 100644 index 00000000..4a3b70b5 --- /dev/null +++ b/pkg/engine/call.go @@ -0,0 +1,95 @@ +package engine + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/gptscript-ai/gptscript/pkg/types" +) + +func (e *Engine) runCall(ctx Context, tool types.Tool, input string) (*Return, error) { + interpreter, body, _ := strings.Cut(tool.Instructions, "\n") + + fields := strings.Fields(interpreter) + if len(fields) < 2 { + return nil, fmt.Errorf("invalid tool call, no target tool found in %s", tool.Instructions) + } + toolRef := strings.Join(fields[1:], " ") + + toolName, args := types.SplitArg(toolRef) + + toolNameParts := strings.Fields(toolName) + + toolName = toolNameParts[0] + toolNameArgs := toolNameParts[1:] + + targetTools, ok := tool.ToolMapping[toolName] + if !ok || len(targetTools) == 0 { + return nil, fmt.Errorf("target tool %s not found, must reference in `tools:` fields", toolName) + } + + ref := types.ToolReference{ + Reference: toolName, + Arg: args, + ToolID: targetTools[0].ToolID, + } + + newInput, err := types.GetToolRefInput(ctx.Program, ref, input) + if err != nil { + return nil, err + } + + newInput, err = mergeInputs(input, newInput) + if err != nil { + return nil, fmt.Errorf("failed to merge inputs: %w", err) + } + + newInput, err = mergeInputs(newInput, toString(map[string]string{ + "TOOL_CALL_ARGS": strings.Join(toolNameArgs, " "), + "TOOL_CALL_BODY": body, + })) + if err != nil { + return nil, fmt.Errorf("failed to merge inputs for tool calls: %w", err) + } + + newCtx := ctx + newCtx.Tool = ctx.Program.ToolSet[ref.ToolID] + + return e.Start(newCtx, newInput) +} + +func toString(data map[string]string) string { + out, err := json.Marshal(data) + if err != nil { + // this will never happen + panic(err) + } + return string(out) +} + +func mergeInputs(base, overlay string) (string, error) { + baseMap := map[string]interface{}{} + overlayMap := map[string]interface{}{} + + if overlay == "" || overlay == "{}" { + return base, nil + } + + if base != "" { + if err := json.Unmarshal([]byte(base), &baseMap); err != nil { + return "", fmt.Errorf("failed to unmarshal base input: %w", err) + } + } + + if err := json.Unmarshal([]byte(overlay), &overlayMap); err != nil { + return "", fmt.Errorf("failed to unmarshal overlay input: %w", err) + } + + for k, v := range overlayMap { + baseMap[k] = v + } + + out, err := json.Marshal(baseMap) + return string(out), err +} diff --git a/pkg/engine/cmd.go b/pkg/engine/cmd.go index 5b27a579..e7671436 100644 --- a/pkg/engine/cmd.go +++ b/pkg/engine/cmd.go @@ -65,7 +65,7 @@ func compressEnv(envs []string) (result []string) { return } -func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCategory ToolCategory) (cmdOut string, cmdErr error) { +func (e *Engine) runCommand(ctx Context, tool types.Tool, input string) (cmdOut string, cmdErr error) { id := counter.Next() var combinedOutput string @@ -119,15 +119,19 @@ func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCate instructions = append(instructions, inputContext.Content) } - var extraEnv = []string{ + extraEnv := []string{ strings.TrimSpace("GPTSCRIPT_CONTEXT=" + strings.Join(instructions, "\n")), } - cmd, stop, err := e.newCommand(ctx.Ctx, extraEnv, tool, input, true) + + commandCtx, cancel := context.WithCancel(ctx.Ctx) + defer cancel() + + cmd, stop, err := e.newCommand(commandCtx, extraEnv, tool, input, true) if err != nil { - if toolCategory == NoCategory { + if ctx.ToolCategory == NoCategory && ctx.Parent != nil { return fmt.Sprintf("ERROR: got (%v) while parsing command", err), nil } - return "", err + return "", fmt.Errorf("got (%v) while parsing command", err) } defer stop() @@ -149,20 +153,28 @@ func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCate result *bytes.Buffer ) + if tool.Stdin { + cmd.Stdin = strings.NewReader(input) + } cmd.Stdout = io.MultiWriter(stdout, stdoutAndErr, progressOut) cmd.Stderr = io.MultiWriter(stdoutAndErr, progressOut, os.Stderr) result = stdout + defer func() { + combinedOutput = stdoutAndErr.String() + }() + + ctx.OnUserCancel(commandCtx, cancel) - if err := cmd.Run(); err != nil { - if toolCategory == NoCategory { + if err := cmd.Run(); err != nil && (commandCtx.Err() == nil || ctx.Ctx.Err() != nil) { + // If the command failed and the context hasn't been canceled, then return the error. + if ctx.ToolCategory == NoCategory && ctx.Parent != nil { + // If this is a sub-call, then don't return the error; return the error as a message so that the LLM can retry. return fmt.Sprintf("ERROR: got (%v) while running tool, OUTPUT: %s", err, stdoutAndErr), nil } - log.Errorf("failed to run tool [%s] cmd %v: %v", tool.Parameters.Name, cmd.Args, err) - combinedOutput = stdoutAndErr.String() - return "", fmt.Errorf("ERROR: %s: %w", result, err) + log.Errorf("failed to run tool [%s] cmd %v: %v", tool.Name, cmd.Args, err) + return "", fmt.Errorf("ERROR: %s: %w", stdoutAndErr, err) } - combinedOutput = stdoutAndErr.String() return result.String(), IsChatFinishMessage(result.String()) } @@ -222,7 +234,7 @@ func appendInputAsEnv(env []string, input string) []string { newEnv = appendEnv(newEnv, "GPTSCRIPT_INPUT", input) - if err := json.Unmarshal([]byte(input), &data); err != nil { + if err := dec.Decode(&data); err != nil { // ignore invalid JSON return newEnv } @@ -288,9 +300,8 @@ func (e *Engine) newCommand(ctx context.Context, extraEnv []string, tool types.T args = args[1:] } - var ( - stop = func() {} - ) + ctx, cancel := context.WithCancel(ctx) + stop := cancel if strings.TrimSpace(rest) != "" { f, err := os.CreateTemp(env.Getenv("GPTSCRIPT_TMPDIR", envvars), version.ProgramName+requiredFileExtensions[args[0]]) @@ -299,6 +310,7 @@ func (e *Engine) newCommand(ctx context.Context, extraEnv []string, tool types.T } stop = func() { _ = os.Remove(f.Name()) + cancel() } _, err = f.Write([]byte(rest)) diff --git a/pkg/engine/daemon.go b/pkg/engine/daemon.go index f0a1c10c..3a0ecba6 100644 --- a/pkg/engine/daemon.go +++ b/pkg/engine/daemon.go @@ -11,6 +11,8 @@ import ( "sync" "time" + cryptorand "crypto/rand" + "github.com/gptscript-ai/gptscript/pkg/system" "github.com/gptscript-ai/gptscript/pkg/types" ) @@ -19,7 +21,8 @@ var ports Ports type Ports struct { daemonPorts map[string]int64 - daemonsRunning map[string]struct{} + daemonTokens map[string]string + daemonsRunning map[string]func() daemonLock sync.Mutex startPort, endPort int64 @@ -57,6 +60,17 @@ func CloseDaemons() { ports.daemonWG.Wait() } +func StopDaemon(url string) { + ports.daemonLock.Lock() + defer ports.daemonLock.Unlock() + + if stop := ports.daemonsRunning[url]; stop != nil { + stop() + } + + delete(ports.daemonsRunning, url) +} + func nextPort() int64 { if ports.startPort == 0 { ports.startPort = 10240 @@ -108,7 +122,30 @@ func getPath(instructions string) (string, string) { return strings.TrimSpace(rest), strings.TrimSpace(value) } -func (e *Engine) startDaemon(tool types.Tool) (string, error) { +func getDaemonToken(toolID string) (string, error) { + token, ok := ports.daemonTokens[toolID] + if !ok { + // Generate a new token. + tokenBytes := make([]byte, 50) + count, err := cryptorand.Read(tokenBytes) + if err != nil { + return "", fmt.Errorf("failed to generate daemon token: %w", err) + } else if count != len(tokenBytes) { + return "", fmt.Errorf("failed to generate daemon token") + } + + token = fmt.Sprintf("%x", tokenBytes) + + if ports.daemonTokens == nil { + ports.daemonTokens = map[string]string{} + } + ports.daemonTokens[toolID] = token + } + + return token, nil +} + +func (e *Engine) startDaemon(tool types.Tool) (string, string, error) { ports.daemonLock.Lock() defer ports.daemonLock.Unlock() @@ -116,10 +153,15 @@ func (e *Engine) startDaemon(tool types.Tool) (string, error) { instructions, path := getPath(instructions) tool.Instructions = types.CommandPrefix + instructions + token, err := getDaemonToken(tool.ID) + if err != nil { + return "", "", err + } + port, ok := ports.daemonPorts[tool.ID] url := fmt.Sprintf("http://127.0.0.1:%d%s", port, path) - if ok { - return url, nil + if ok && ports.daemonsRunning[url] != nil { + return url, token, nil } if ports.daemonCtx == nil { @@ -138,18 +180,19 @@ func (e *Engine) startDaemon(tool types.Tool) (string, error) { cmd, stop, err := e.newCommand(ctx, []string{ fmt.Sprintf("PORT=%d", port), fmt.Sprintf("GPTSCRIPT_PORT=%d", port), + fmt.Sprintf("GPTSCRIPT_DAEMON_TOKEN=%s", token), }, tool, "{}", false, ) if err != nil { - return url, err + return url, "", err } r, w, err := os.Pipe() if err != nil { - return "", err + return "", "", err } // Loop back to gptscript to help with process supervision @@ -164,32 +207,32 @@ func (e *Engine) startDaemon(tool types.Tool) (string, error) { return w.Close() } - log.Infof("launched [%s][%s] port [%d] %v", tool.Parameters.Name, tool.ID, port, cmd.Args) + log.Infof("launched [%s][%s] port [%d] %v", tool.Name, tool.ID, port, cmd.Args) if err := cmd.Start(); err != nil { stop() - return url, err + return url, "", err } if ports.daemonPorts == nil { ports.daemonPorts = map[string]int64{} - ports.daemonsRunning = map[string]struct{}{} + ports.daemonsRunning = map[string]func(){} } ports.daemonPorts[tool.ID] = port - ports.daemonsRunning[url] = struct{}{} + ports.daemonsRunning[url] = stop - killedCtx, cancel := context.WithCancelCause(ctx) - defer cancel(nil) + killedCtx, killedCancel := context.WithCancelCause(ctx) + defer killedCancel(nil) ports.daemonWG.Add(1) go func() { err := cmd.Wait() if err != nil { - log.Debugf("daemon exited tool [%s] %v: %v", tool.Parameters.Name, cmd.Args, err) + log.Debugf("daemon exited tool [%s] %v: %v", tool.Name, cmd.Args, err) } _ = r.Close() _ = w.Close() - cancel(err) + killedCancel(err) stop() ports.daemonLock.Lock() defer ports.daemonLock.Unlock() @@ -206,20 +249,20 @@ func (e *Engine) startDaemon(tool types.Tool) (string, error) { _, _ = io.ReadAll(resp.Body) _ = resp.Body.Close() }() - return url, nil + return url, token, nil } select { case <-killedCtx.Done(): - return url, fmt.Errorf("daemon failed to start: %w", context.Cause(killedCtx)) + return url, "", fmt.Errorf("daemon failed to start: %w", context.Cause(killedCtx)) case <-time.After(time.Second): } } - return url, fmt.Errorf("timeout waiting for 200 response from GET %s", url) + return url, "", fmt.Errorf("timeout waiting for 200 response from GET %s", url) } -func (e *Engine) runDaemon(ctx context.Context, prg *types.Program, tool types.Tool, input string) (cmdRet *Return, cmdErr error) { - url, err := e.startDaemon(tool) +func (e *Engine) runDaemon(ctx Context, tool types.Tool, input string) (cmdRet *Return, cmdErr error) { + url, _, err := e.startDaemon(tool) if err != nil { return nil, err } @@ -227,5 +270,5 @@ func (e *Engine) runDaemon(ctx context.Context, prg *types.Program, tool types.T tool.Instructions = strings.Join(append([]string{ types.CommandPrefix + url, }, strings.Split(tool.Instructions, "\n")[1:]...), "\n") - return e.runHTTP(ctx, prg, tool, input) + return e.runHTTP(ctx, tool, input) } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 0665991c..c509af9c 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -4,25 +4,36 @@ import ( "context" "encoding/json" "fmt" + "os" + "slices" + "strconv" "strings" "sync" - "github.com/gptscript-ai/gptscript/pkg/config" - gcontext "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/counter" "github.com/gptscript-ai/gptscript/pkg/types" "github.com/gptscript-ai/gptscript/pkg/version" ) +var maxConsecutiveToolCalls = 50 + +const AbortedSuffix = "\n\nABORTED BY USER" + +func init() { + if val := os.Getenv("GPTSCRIPT_MAX_CONSECUTIVE_TOOL_CALLS"); val != "" { + if i, err := strconv.Atoi(val); err == nil && i > 0 { + maxConsecutiveToolCalls = i + } + } +} + type Model interface { - Call(ctx context.Context, messageRequest types.CompletionRequest, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) - ProxyInfo() (string, string, error) + Call(ctx context.Context, messageRequest types.CompletionRequest, env []string, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) + ProxyInfo([]string) (string, string, error) } type RuntimeManager interface { GetContext(ctx context.Context, tool types.Tool, cmd, env []string) (string, []string, error) - EnsureCredentialHelpers(ctx context.Context) error - SetUpCredentialHelpers(ctx context.Context, cliCfg *config.CLIConfig) error } type Engine struct { @@ -30,6 +41,11 @@ type Engine struct { RuntimeManager RuntimeManager Env []string Progress chan<- types.CompletionStatus + MCPRunner MCPRunner +} + +type MCPRunner interface { + Run(ctx Context, progress chan<- types.CompletionStatus, tool types.Tool, input string) (string, error) } type State struct { @@ -83,7 +99,8 @@ type Context struct { Engine *Engine Program *types.Program // Input is saved only so that we can render display text, don't use otherwise - Input string + Input string + userCancel <-chan struct{} } type ChatHistory struct { @@ -179,6 +196,18 @@ func (c *Context) MarshalJSON() ([]byte, error) { return json.Marshal(c.GetCallContext()) } +func (c *Context) OnUserCancel(ctx context.Context, cancel func()) { + go func() { + select { + case <-ctx.Done(): + // If the context is canceled, then nothing to do. + case <-c.userCancel: + // If the user is requesting a cancel, then cancel the context. + cancel() + } + }() +} + type toolCategoryKey struct{} func WithToolCategory(ctx context.Context, toolCategory ToolCategory) context.Context { @@ -190,7 +219,7 @@ func ToolCategoryFromContext(ctx context.Context) ToolCategory { return category } -func NewContext(ctx context.Context, prg *types.Program, input string) (Context, error) { +func NewContext(ctx context.Context, prg *types.Program, input string, userCancel <-chan struct{}) (Context, error) { category := ToolCategoryFromContext(ctx) callCtx := Context{ @@ -199,9 +228,10 @@ func NewContext(ctx context.Context, prg *types.Program, input string) (Context, Tool: prg.ToolSet[prg.EntryToolID], ToolCategory: category, }, - Ctx: ctx, - Program: prg, - Input: input, + Ctx: ctx, + Program: prg, + Input: input, + userCancel: userCancel, } agentGroup, err := callCtx.Tool.GetToolsByType(prg, types.ToolTypeAgent) @@ -242,6 +272,7 @@ func (c *Context) SubCallContext(ctx context.Context, input, toolID, callID stri Program: c.Program, CurrentReturn: c.CurrentReturn, Input: input, + userCancel: c.userCancel, }, nil } @@ -259,13 +290,13 @@ func (c *Context) WrappedContext(e *Engine) context.Context { } func populateMessageParams(ctx Context, completion *types.CompletionRequest, tool types.Tool) error { - completion.Model = tool.Parameters.ModelName - completion.MaxTokens = tool.Parameters.MaxTokens - completion.JSONResponse = tool.Parameters.JSONResponse - completion.Cache = tool.Parameters.Cache - completion.Chat = tool.Parameters.Chat - completion.Temperature = tool.Parameters.Temperature - completion.InternalSystemPrompt = tool.Parameters.InternalPrompt + completion.Model = tool.ModelName + completion.MaxTokens = tool.MaxTokens + completion.JSONResponse = tool.JSONResponse + completion.Cache = tool.Cache + completion.Chat = tool.Chat + completion.Temperature = tool.Temperature + completion.InternalSystemPrompt = tool.InternalPrompt if tool.Chat && completion.InternalSystemPrompt == nil { completion.InternalSystemPrompt = new(bool) @@ -281,34 +312,59 @@ func populateMessageParams(ctx Context, completion *types.CompletionRequest, too return nil } +func (e *Engine) runMCPInvoke(ctx Context, tool types.Tool, input string) (*Return, error) { + output, err := e.MCPRunner.Run(ctx, e.Progress, tool, input) + if err != nil { + return nil, fmt.Errorf("failed to run MCP invoke: %w", err) + } + + return &Return{ + Result: &output, + }, nil +} + func (e *Engine) runCommandTools(ctx Context, tool types.Tool, input string) (*Return, error) { if tool.IsHTTP() { - return e.runHTTP(ctx.Ctx, ctx.Program, tool, input) + return e.runHTTP(ctx, tool, input) } else if tool.IsDaemon() { - return e.runDaemon(ctx.Ctx, ctx.Program, tool, input) + return e.runDaemon(ctx, tool, input) } else if tool.IsOpenAPI() { - return e.runOpenAPI(tool, input) + return e.runOpenAPI(ctx, tool, input) } else if tool.IsEcho() { return e.runEcho(tool) + } else if tool.IsCall() { + return e.runCall(ctx, tool, input) } - s, err := e.runCommand(ctx, tool, input, ctx.ToolCategory) - if err != nil { - return nil, err - } + s, err := e.runCommand(ctx, tool, input) return &Return{ Result: &s, - }, nil + }, err } -func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) { +func (e *Engine) Start(ctx Context, input string) (ret *Return, err error) { tool := ctx.Tool defer func() { if ret != nil && ret.State != nil { ret.State.Input = input } + select { + case <-ctx.userCancel: + if ret == nil { + ret = new(Return) + } + if ret.Result == nil { + ret.Result = new(string) + } + *ret.Result += AbortedSuffix + default: + } }() + if tool.IsMCPInvoke() { + return e.runMCPInvoke(ctx, tool, input) + } + if tool.IsCommand() { return e.runCommandTools(ctx, tool, input) } @@ -333,7 +389,7 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) { }) } - return e.complete(ctx.Ctx, &State{ + return e.complete(ctx, &State{ Completion: completion, }) } @@ -345,6 +401,7 @@ func addUpdateSystem(ctx Context, tool types.Tool, msgs []types.CompletionMessag instructions = append(instructions, context.Content) } + tool.Instructions = strings.TrimPrefix(tool.Instructions, types.PromptPrefix) if tool.Instructions != "" { instructions = append(instructions, tool.Instructions) } @@ -365,7 +422,7 @@ func addUpdateSystem(ctx Context, tool types.Tool, msgs []types.CompletionMessag return append([]types.CompletionMessage{msg}, msgs...) } -func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) { +func (e *Engine) complete(ctx Context, state *State) (*Return, error) { var ( progress = make(chan types.CompletionStatus) ret = Return{ @@ -389,9 +446,38 @@ func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) { } }() - resp, err := e.Model.Call(gcontext.WithEnv(ctx, e.Env), state.Completion, progress) + // Limit the number of consecutive tool calls. + // We don't want the LLM to call tools unrestricted or get stuck in an error loop. + var messagesSinceLastUserMessage int + for _, msg := range slices.Backward(state.Completion.Messages) { + if msg.Role == types.CompletionMessageRoleTypeUser { + break + } else if msg.Role == types.CompletionMessageRoleTypeAssistant { + for _, content := range msg.Content { + // If this message is requesting that a tool call be made, then count it towards the limit. + if content.ToolCall != nil { + messagesSinceLastUserMessage++ + break + } + } + } + } + + if messagesSinceLastUserMessage > maxConsecutiveToolCalls { + msg := fmt.Sprintf("We cannot continue because the number of consecutive tool calls is limited to %d.", maxConsecutiveToolCalls) + ret.State.Completion.Messages = append(state.Completion.Messages, types.CompletionMessage{ + Role: types.CompletionMessageRoleTypeAssistant, + Content: []types.ContentPart{{Text: msg}}, + }) + // Setting this ensures that chat continues as expected when we hit this problem. + state.Pending = map[string]types.CompletionToolCall{} + ret.Result = &msg + return &ret, nil + } + + resp, err := e.Model.Call(ctx.WrappedContext(e), state.Completion, e.Env, progress) if err != nil { - return nil, err + return nil, fmt.Errorf("failed calling model for completion: %w", err) } state.Completion.Messages = append(state.Completion.Messages, *resp) @@ -434,7 +520,17 @@ func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) { return &ret, nil } -func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (*Return, error) { +func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (ret *Return, _ error) { + defer func() { + select { + case <-ctx.userCancel: + if ret.Result == nil { + ret.Result = new(string) + } + *ret.Result += AbortedSuffix + default: + } + }() if ctx.Tool.IsCommand() { var input string if len(results) == 1 { @@ -468,7 +564,7 @@ func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (*Re } } - ret := Return{ + ret = &Return{ State: state, Calls: map[string]Call{}, } @@ -484,7 +580,7 @@ func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (*Re if len(ret.Calls) > 0 { // Outstanding tool calls still pending - return &ret, nil + return ret, nil } for _, content := range state.Completion.Messages[len(state.Completion.Messages)-1].Content { @@ -519,5 +615,5 @@ func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (*Re return nil, err } - return e.complete(ctx.Ctx, state) + return e.complete(ctx, state) } diff --git a/pkg/engine/http.go b/pkg/engine/http.go index a81f1bb3..a9a635e8 100644 --- a/pkg/engine/http.go +++ b/pkg/engine/http.go @@ -1,13 +1,14 @@ package engine import ( - "context" "encoding/json" "fmt" "io" + "maps" "net/http" "net/url" "os" + "slices" "strings" "github.com/gptscript-ai/gptscript/pkg/types" @@ -15,9 +16,14 @@ import ( const DaemonURLSuffix = ".daemon.gptscript.local" -func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Tool, input string) (cmdRet *Return, cmdErr error) { +func (e *Engine) runHTTP(ctx Context, tool types.Tool, input string) (cmdRet *Return, cmdErr error) { envMap := map[string]string{} + for _, env := range appendInputAsEnv(nil, input) { + k, v, _ := strings.Cut(env, "=") + envMap[k] = v + } + for _, env := range e.Env { k, v, _ := strings.Cut(env, "=") envMap[k] = v @@ -25,7 +31,7 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too toolURL := strings.Split(tool.Instructions, "\n")[0][2:] toolURL = os.Expand(toolURL, func(s string) string { - return envMap[s] + return url.PathEscape(envMap[s]) }) parsed, err := url.Parse(toolURL) @@ -33,17 +39,21 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too return nil, err } + var ( + requestedEnvVars map[string]struct{} + daemonToken string + ) if strings.HasSuffix(parsed.Hostname(), DaemonURLSuffix) { referencedToolName := strings.TrimSuffix(parsed.Hostname(), DaemonURLSuffix) referencedToolRefs, ok := tool.ToolMapping[referencedToolName] if !ok || len(referencedToolRefs) != 1 { return nil, fmt.Errorf("invalid reference [%s] to tool [%s] from [%s], missing \"tools: %s\" parameter", toolURL, referencedToolName, tool.Source, referencedToolName) } - referencedTool, ok := prg.ToolSet[referencedToolRefs[0].ToolID] + referencedTool, ok := ctx.Program.ToolSet[referencedToolRefs[0].ToolID] if !ok { return nil, fmt.Errorf("failed to find tool [%s] for [%s]", referencedToolName, parsed.Hostname()) } - toolURL, err = e.startDaemon(referencedTool) + toolURL, daemonToken, err = e.startDaemon(referencedTool) if err != nil { return nil, err } @@ -53,6 +63,14 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too } parsed.Host = toolURLParsed.Host toolURL = parsed.String() + + metadataEnvVars := strings.Split(referencedTool.MetaData["requestedEnvVars"], ",") + requestedEnvVars = make(map[string]struct{}, len(metadataEnvVars)) + for _, e := range metadataEnvVars { + if e != "" { + requestedEnvVars[e] = struct{}{} + } + } } if tool.Blocking { @@ -61,12 +79,47 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too }, nil } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, toolURL, strings.NewReader(input)) + if body, ok := envMap["BODY"]; ok { + input = body + } + + req, err := http.NewRequestWithContext(ctx.Ctx, http.MethodPost, toolURL, strings.NewReader(input)) if err != nil { return nil, err } - req.Header.Set("X-GPTScript-Tool-Name", tool.Parameters.Name) + if daemonToken != "" { + req.Header.Add("X-GPTScript-Daemon-Token", daemonToken) + } + + for _, k := range slices.Sorted(maps.Keys(envMap)) { + if _, ok := requestedEnvVars[k]; ok || strings.HasPrefix(k, "GPTSCRIPT_WORKSPACE_") { + req.Header.Add("X-GPTScript-Env", k+"="+envMap[k]) + } + } + + for _, prefix := range strings.Split(envMap["GPTSCRIPT_HTTP_ENV_PREFIX"], ",") { + if prefix == "" { + continue + } + for _, k := range slices.Sorted(maps.Keys(envMap)) { + if strings.HasPrefix(k, prefix) { + req.Header.Add("X-GPTScript-Env", k+"="+envMap[k]) + } + } + } + + for _, k := range strings.Split(envMap["GPTSCRIPT_HTTP_ENV"], ",") { + if k == "" { + continue + } + v := envMap[k] + if v != "" { + req.Header.Add("X-GPTScript-Env", k+"="+v) + } + } + + req.Header.Set("X-GPTScript-Tool-Name", tool.Name) if err := json.Unmarshal([]byte(input), &map[string]any{}); err == nil { req.Header.Set("Content-Type", "application/json") @@ -74,6 +127,13 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too req.Header.Set("Content-Type", "text/plain") } + // If the user canceled the run, then don't make the request. + select { + case <-ctx.userCancel: + return &Return{}, nil + default: + } + resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err @@ -81,8 +141,8 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too defer resp.Body.Close() if resp.StatusCode > 299 { - _, _ = io.ReadAll(resp.Body) - return nil, fmt.Errorf("error in request to [%s] [%d]: %s", toolURL, resp.StatusCode, resp.Status) + body, _ := io.ReadAll(resp.Body) + return nil, fmt.Errorf("error in request to [%s] [%d]: %s: %s", toolURL, resp.StatusCode, resp.Status, body) } content, err := io.ReadAll(resp.Body) diff --git a/pkg/engine/openapi.go b/pkg/engine/openapi.go index a951bd37..2e79bc38 100644 --- a/pkg/engine/openapi.go +++ b/pkg/engine/openapi.go @@ -145,7 +145,7 @@ func (e *Engine) runOpenAPIRevamp(tool types.Tool, input string) (*Return, error } res = &Return{ - Result: ptr(result), + Result: &result, } } @@ -156,7 +156,7 @@ func (e *Engine) runOpenAPIRevamp(tool types.Tool, input string) (*Return, error // The tool itself will have instructions regarding the HTTP request that needs to be made. // The tools Instructions field will be in the format "#!sys.openapi '{Instructions JSON}'", // where {Instructions JSON} is a JSON string of type OpenAPIInstructions. -func (e *Engine) runOpenAPI(tool types.Tool, input string) (*Return, error) { +func (e *Engine) runOpenAPI(ctx Context, tool types.Tool, input string) (*Return, error) { if os.Getenv("GPTSCRIPT_OPENAPI_REVAMP") == "true" { return e.runOpenAPIRevamp(tool, input) } @@ -197,19 +197,17 @@ func (e *Engine) runOpenAPI(tool types.Tool, input string) (*Return, error) { return nil, fmt.Errorf("failed to create request: %w", err) } - // Check for authentication (only if using HTTPS or localhost) - if u.Scheme == "https" || u.Hostname() == "localhost" || u.Hostname() == "127.0.0.1" { - if len(instructions.SecurityInfos) > 0 { - if err := openapi.HandleAuths(req, envMap, instructions.SecurityInfos); err != nil { - return nil, fmt.Errorf("error setting up authentication: %w", err) - } + // Check for authentication + if len(instructions.SecurityInfos) > 0 { + if err := openapi.HandleAuths(req, envMap, instructions.SecurityInfos); err != nil { + return nil, fmt.Errorf("error setting up authentication: %w", err) } + } - // If there is a bearer token set for the whole server, and no Authorization header has been defined, use it. - if token, ok := envMap["GPTSCRIPT_"+env.ToEnvLike(u.Hostname())+"_BEARER_TOKEN"]; ok { - if req.Header.Get("Authorization") == "" { - req.Header.Set("Authorization", "Bearer "+token) - } + // If there is a bearer token set for the whole server, and no Authorization header has been defined, use it. + if token, ok := envMap["GPTSCRIPT_"+env.ToEnvLike(u.Hostname())+"_BEARER_TOKEN"]; ok { + if req.Header.Get("Authorization") == "" { + req.Header.Set("Authorization", "Bearer "+token) } } @@ -268,6 +266,13 @@ func (e *Engine) runOpenAPI(tool types.Tool, input string) (*Return, error) { req.Body = io.NopCloser(&body) } + // If the user canceled the run, then don't make the request. + select { + case <-ctx.userCancel: + return &Return{}, nil + default: + } + // Make the request resp, err := http.DefaultClient.Do(req) if err != nil { diff --git a/pkg/gptscript/gptscript.go b/pkg/gptscript/gptscript.go index 679eb503..b7facbd1 100644 --- a/pkg/gptscript/gptscript.go +++ b/pkg/gptscript/gptscript.go @@ -2,6 +2,7 @@ package gptscript import ( "context" + "errors" "fmt" "os" "os/user" @@ -9,14 +10,16 @@ import ( "slices" "strings" + openai2 "github.com/gptscript-ai/chat-completion-client" "github.com/gptscript-ai/gptscript/pkg/builtin" "github.com/gptscript-ai/gptscript/pkg/cache" "github.com/gptscript-ai/gptscript/pkg/config" context2 "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/engine" - "github.com/gptscript-ai/gptscript/pkg/hash" "github.com/gptscript-ai/gptscript/pkg/llm" + "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/mcp" "github.com/gptscript-ai/gptscript/pkg/monitor" "github.com/gptscript-ai/gptscript/pkg/mvl" "github.com/gptscript-ai/gptscript/pkg/openai" @@ -33,13 +36,15 @@ import ( var log = mvl.Package() type GPTScript struct { - Registry *llm.Registry - Runner *runner.Runner - Cache *cache.Client - WorkspacePath string - DeleteWorkspaceOnClose bool - ExtraEnv []string - close func() + Registry *llm.Registry + Runner *runner.Runner + Cache *cache.Client + CredentialStoreFactory credentials.StoreFactory + DefaultCredentialContexts []string + WorkspacePath string + DeleteWorkspaceOnClose bool + ExtraEnv []string + close func() } type Options struct { @@ -52,7 +57,10 @@ type Options struct { Quiet *bool Workspace string DisablePromptServer bool + SystemToolsDir string Env []string + CredentialStore string + CredentialToolsEnv []string } func Complete(opts ...Options) Options { @@ -63,12 +71,15 @@ func Complete(opts ...Options) Options { result.Runner = runner.Complete(result.Runner, opt.Runner) result.OpenAI = openai.Complete(result.OpenAI, opt.OpenAI) + result.SystemToolsDir = types.FirstSet(opt.SystemToolsDir, result.SystemToolsDir) result.CredentialContexts = opt.CredentialContexts result.Quiet = types.FirstSet(opt.Quiet, result.Quiet) result.Workspace = types.FirstSet(opt.Workspace, result.Workspace) result.Env = append(result.Env, opt.Env...) + result.CredentialToolsEnv = append(result.CredentialToolsEnv, opt.CredentialToolsEnv...) result.DisablePromptServer = types.FirstSet(opt.DisablePromptServer, result.DisablePromptServer) result.DefaultModelProvider = types.FirstSet(opt.DefaultModelProvider, result.DefaultModelProvider) + result.CredentialStore = types.FirstSet(opt.CredentialStore, result.CredentialStore) } if result.Quiet == nil { @@ -77,6 +88,9 @@ func Complete(opts ...Options) Options { if len(result.Env) == 0 { result.Env = os.Environ() } + if len(result.CredentialToolsEnv) == 0 { + result.CredentialToolsEnv = result.Env + } if len(result.CredentialContexts) == 0 { result.CredentialContexts = []string{credentials.DefaultCredentialContext} } @@ -98,15 +112,25 @@ func New(ctx context.Context, o ...Options) (*GPTScript, error) { return nil, err } + if opts.CredentialStore != "" { + cliCfg.CredentialsStore = opts.CredentialStore + } + if opts.Runner.RuntimeManager == nil { - opts.Runner.RuntimeManager = runtimes.Default(cacheClient.CacheDir()) + opts.Runner.RuntimeManager = runtimes.Default(cacheClient.CacheDir(), opts.SystemToolsDir) } - if err := opts.Runner.RuntimeManager.SetUpCredentialHelpers(context.Background(), cliCfg); err != nil { + simplerRunner, err := newSimpleRunner(cacheClient, opts.Runner.RuntimeManager, opts.CredentialToolsEnv) + if err != nil { return nil, err } - credStore, err := credentials.NewStore(cliCfg, opts.Runner.RuntimeManager, opts.CredentialContexts, cacheClient.CacheDir()) + storeFactory, err := credentials.NewFactory(ctx, cliCfg, opts.Runner.CredentialOverrides, simplerRunner) + if err != nil { + return nil, err + } + + credStore, err := storeFactory.NewStore(opts.CredentialContexts) if err != nil { return nil, err } @@ -157,17 +181,33 @@ func New(ctx context.Context, o ...Options) (*GPTScript, error) { } return &GPTScript{ - Registry: registry, - Runner: runner, - Cache: cacheClient, - WorkspacePath: opts.Workspace, - DeleteWorkspaceOnClose: opts.Workspace == "", - ExtraEnv: extraEnv, - close: closeServer, + Registry: registry, + Runner: runner, + Cache: cacheClient, + CredentialStoreFactory: storeFactory, + DefaultCredentialContexts: opts.CredentialContexts, + WorkspacePath: opts.Workspace, + DeleteWorkspaceOnClose: opts.Workspace == "", + ExtraEnv: extraEnv, + close: closeServer, }, nil } func (g *GPTScript) getEnv(env []string) ([]string, error) { + var ( + id string + ) + + scheme, rest, isScheme := strings.Cut(g.WorkspacePath, "://") + if isScheme && scheme == "directory" { + id = g.WorkspacePath + g.WorkspacePath = rest + } else if isScheme { + id = g.WorkspacePath + g.WorkspacePath = "" + g.DeleteWorkspaceOnClose = true + } + if g.WorkspacePath == "" { var err error g.WorkspacePath, err = os.MkdirTemp("", "gptscript-workspace-*") @@ -184,9 +224,12 @@ func (g *GPTScript) getEnv(env []string) ([]string, error) { if err := os.MkdirAll(g.WorkspacePath, 0700); err != nil { return nil, err } + if id == "" { + id = "directory://" + g.WorkspacePath + } return slices.Concat(g.ExtraEnv, env, []string{ fmt.Sprintf("GPTSCRIPT_WORKSPACE_DIR=%s", g.WorkspacePath), - fmt.Sprintf("GPTSCRIPT_WORKSPACE_ID=%s", hash.ID(g.WorkspacePath)), + fmt.Sprintf("GPTSCRIPT_WORKSPACE_ID=%s", id), }), nil } @@ -202,25 +245,25 @@ func makeAbsolute(path string) (string, error) { return filepath.Abs(path) } -func (g *GPTScript) Chat(ctx context.Context, prevState runner.ChatState, prg types.Program, envs []string, input string) (runner.ChatResponse, error) { +func (g *GPTScript) Chat(ctx context.Context, prevState runner.ChatState, prg types.Program, envs []string, input string, opts runner.RunOptions) (runner.ChatResponse, error) { envs, err := g.getEnv(envs) if err != nil { return runner.ChatResponse{}, err } - return g.Runner.Chat(ctx, prevState, prg, envs, input) + return g.Runner.Chat(ctx, prevState, prg, envs, input, opts) } -func (g *GPTScript) Run(ctx context.Context, prg types.Program, envs []string, input string) (string, error) { +func (g *GPTScript) Run(ctx context.Context, prg types.Program, envs []string, input string, opts runner.RunOptions) (string, error) { envs, err := g.getEnv(envs) if err != nil { return "", err } - return g.Runner.Run(ctx, prg, envs, input) + return g.Runner.Run(ctx, prg, envs, input, opts) } -func (g *GPTScript) Close(closeDaemons bool) { +func (g *GPTScript) Close(closeDaemonsAndMCP bool) { if g.DeleteWorkspaceOnClose && g.WorkspacePath != "" { if err := os.RemoveAll(g.WorkspacePath); err != nil { log.Errorf("failed to delete workspace %s: %s", g.WorkspacePath, err) @@ -229,8 +272,11 @@ func (g *GPTScript) Close(closeDaemons bool) { g.close() - if closeDaemons { + if closeDaemonsAndMCP { engine.CloseDaemons() + if err := mcp.DefaultLoader.Close(); err != nil { + log.Errorf("failed to close MCP loader: %s", err) + } } } @@ -245,6 +291,78 @@ func (g *GPTScript) ListTools(_ context.Context, prg types.Program) []types.Tool return prg.TopLevelTools() } -func (g *GPTScript) ListModels(ctx context.Context, providers ...string) ([]string, error) { +func (g *GPTScript) ListModels(ctx context.Context, providers ...string) ([]openai2.Model, error) { return g.Registry.ListModels(ctx, providers...) } + +type simpleRunner struct { + cache *cache.Client + runner *runner.Runner + env []string +} + +func newSimpleRunner(cache *cache.Client, rm engine.RuntimeManager, env []string) (*simpleRunner, error) { + runner, err := runner.New(noopModel{}, credentials.NoopStore{}, runner.Options{ + RuntimeManager: rm, + MonitorFactory: simpleMonitorFactory{}, + }) + if err != nil { + return nil, err + } + return &simpleRunner{ + cache: cache, + runner: runner, + env: env, + }, nil +} + +func (s *simpleRunner) Load(ctx context.Context, toolName string) (prg types.Program, err error) { + return loader.Program(ctx, toolName, "", loader.Options{ + Cache: s.cache, + }) +} + +func (s *simpleRunner) Run(ctx context.Context, prg types.Program, input string) (output string, err error) { + return s.runner.Run(ctx, prg, s.env, input, runner.RunOptions{}) +} + +type noopModel struct { +} + +func (n noopModel) Call(_ context.Context, _ types.CompletionRequest, _ []string, _ chan<- types.CompletionStatus) (*types.CompletionMessage, error) { + return nil, errors.New("unsupported") +} + +func (n noopModel) ProxyInfo([]string) (string, string, error) { + return "", "", errors.New("unsupported") +} + +type simpleMonitorFactory struct { +} + +func (s simpleMonitorFactory) Start(_ context.Context, _ *types.Program, _ []string, _ string) (runner.Monitor, error) { + return simpleMonitor{}, nil +} + +func (s simpleMonitorFactory) Pause() func() { + //TODO implement me + panic("implement me") +} + +type simpleMonitor struct { +} + +func (s simpleMonitor) Stop(_ context.Context, _ string, _ error) { +} + +func (s simpleMonitor) Event(event runner.Event) { + if event.Type == runner.EventTypeCallProgress { + if !strings.HasPrefix(event.Content, "{") { + fmt.Println(event.Content) + } + } +} + +func (s simpleMonitor) Pause() func() { + return func() {} +} diff --git a/pkg/hash/sha256.go b/pkg/hash/sha256.go index 05209e44..93aee56a 100644 --- a/pkg/hash/sha256.go +++ b/pkg/hash/sha256.go @@ -2,8 +2,8 @@ package hash import ( "crypto/sha256" - "encoding/gob" "encoding/hex" + "encoding/json" ) func ID(parts ...string) string { @@ -26,7 +26,7 @@ func Digest(obj any) string { case string: hash.Write([]byte(v)) default: - if err := gob.NewEncoder(hash).Encode(obj); err != nil { + if err := json.NewEncoder(hash).Encode(obj); err != nil { panic(err) } } diff --git a/pkg/llm/proxy.go b/pkg/llm/proxy.go index 7c3091b3..82b33d02 100644 --- a/pkg/llm/proxy.go +++ b/pkg/llm/proxy.go @@ -15,7 +15,20 @@ import ( "github.com/gptscript-ai/gptscript/pkg/openai" ) -func (r *Registry) ProxyInfo() (string, string, error) { +func (r *Registry) ProxyInfo(env []string) (string, string, error) { + var proxyURL, proxyToken string + for _, e := range env { + if url, ok := strings.CutPrefix(e, "GPTSCRIPT_MODEL_PROVIDER_PROXY_URL="); ok { + proxyURL = url + } else if token, ok := strings.CutPrefix(e, "GPTSCRIPT_MODEL_PROVIDER_PROXY_TOKEN="); ok { + proxyToken = token + } + } + + if proxyToken != "" && proxyURL != "" { + return proxyToken, proxyURL, nil + } + r.proxyLock.Lock() defer r.proxyLock.Unlock() @@ -54,7 +67,7 @@ func (r *Registry) ServeHTTP(w http.ResponseWriter, req *http.Request) { var ( model string - data = map[string]any{} + data map[string]any ) if json.Unmarshal(inBytes, &data) == nil { @@ -65,7 +78,7 @@ func (r *Registry) ServeHTTP(w http.ResponseWriter, req *http.Request) { model = builtin.GetDefaultModel() } - c, err := r.getClient(req.Context(), model) + c, err := r.getClient(req.Context(), model, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -77,7 +90,7 @@ func (r *Registry) ServeHTTP(w http.ResponseWriter, req *http.Request) { return } - auth, targetURL := oai.ProxyInfo() + auth, targetURL := oai.ProxyInfo(nil) if targetURL == "" { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return diff --git a/pkg/llm/registry.go b/pkg/llm/registry.go index 8129c788..d53d96b9 100644 --- a/pkg/llm/registry.go +++ b/pkg/llm/registry.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/google/uuid" + openai2 "github.com/gptscript-ai/chat-completion-client" "github.com/gptscript-ai/gptscript/pkg/env" "github.com/gptscript-ai/gptscript/pkg/openai" "github.com/gptscript-ai/gptscript/pkg/remote" @@ -15,8 +16,8 @@ import ( ) type Client interface { - Call(ctx context.Context, messageRequest types.CompletionRequest, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) - ListModels(ctx context.Context, providers ...string) (result []string, _ error) + Call(ctx context.Context, messageRequest types.CompletionRequest, env []string, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) + ListModels(ctx context.Context, providers ...string) (result []openai2.Model, _ error) Supports(ctx context.Context, modelName string) (bool, error) } @@ -38,7 +39,7 @@ func (r *Registry) AddClient(client Client) error { return nil } -func (r *Registry) ListModels(ctx context.Context, providers ...string) (result []string, _ error) { +func (r *Registry) ListModels(ctx context.Context, providers ...string) (result []openai2.Model, _ error) { for _, v := range r.clients { models, err := v.ListModels(ctx, providers...) if err != nil { @@ -46,7 +47,9 @@ func (r *Registry) ListModels(ctx context.Context, providers ...string) (result } result = append(result, models...) } - sort.Strings(result) + sort.Slice(result, func(i, j int) bool { + return result[i].ID < result[j].ID + }) return result, nil } @@ -78,7 +81,7 @@ func (r *Registry) fastPath(modelName string) Client { return r.clients[0] } -func (r *Registry) getClient(ctx context.Context, modelName string) (Client, error) { +func (r *Registry) getClient(ctx context.Context, modelName string, env []string) (Client, error) { if c := r.fastPath(modelName); c != nil { return c, nil } @@ -101,7 +104,7 @@ func (r *Registry) getClient(ctx context.Context, modelName string) (Client, err if len(errs) > 0 && oaiClient != nil { // Prompt the user to enter their OpenAI API key and try again. - if err := oaiClient.RetrieveAPIKey(ctx); err != nil { + if err := oaiClient.RetrieveAPIKey(ctx, env); err != nil { return nil, err } ok, err := oaiClient.Supports(ctx, modelName) @@ -119,13 +122,13 @@ func (r *Registry) getClient(ctx context.Context, modelName string) (Client, err return nil, errors.Join(errs...) } -func (r *Registry) Call(ctx context.Context, messageRequest types.CompletionRequest, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { +func (r *Registry) Call(ctx context.Context, messageRequest types.CompletionRequest, env []string, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { if messageRequest.Model == "" { return nil, fmt.Errorf("model is required") } if c := r.fastPath(messageRequest.Model); c != nil { - return c.Call(ctx, messageRequest, status) + return c.Call(ctx, messageRequest, env, status) } var errs []error @@ -140,20 +143,20 @@ func (r *Registry) Call(ctx context.Context, messageRequest types.CompletionRequ errs = append(errs, err) } else if ok { - return client.Call(ctx, messageRequest, status) + return client.Call(ctx, messageRequest, env, status) } } if len(errs) > 0 && oaiClient != nil { // Prompt the user to enter their OpenAI API key and try again. - if err := oaiClient.RetrieveAPIKey(ctx); err != nil { + if err := oaiClient.RetrieveAPIKey(ctx, env); err != nil { return nil, err } ok, err := oaiClient.Supports(ctx, messageRequest.Model) if err != nil { return nil, err } else if ok { - return oaiClient.Call(ctx, messageRequest, status) + return oaiClient.Call(ctx, messageRequest, env, status) } } diff --git a/pkg/loader/loader.go b/pkg/loader/loader.go index 80342f2b..626cc87f 100644 --- a/pkg/loader/loader.go +++ b/pkg/loader/loader.go @@ -17,10 +17,10 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/gptscript-ai/gptscript/internal" - "github.com/gptscript-ai/gptscript/pkg/assemble" "github.com/gptscript-ai/gptscript/pkg/builtin" "github.com/gptscript-ai/gptscript/pkg/cache" "github.com/gptscript-ai/gptscript/pkg/hash" + "github.com/gptscript-ai/gptscript/pkg/mcp" "github.com/gptscript-ai/gptscript/pkg/openapi" "github.com/gptscript-ai/gptscript/pkg/parser" "github.com/gptscript-ai/gptscript/pkg/system" @@ -29,6 +29,18 @@ import ( const CacheTimeout = time.Hour +var Remap = map[string]string{} + +func init() { + remap := os.Getenv("GPTSCRIPT_TOOL_REMAP") + for _, pair := range strings.Split(remap, ",") { + k, v, ok := strings.Cut(pair, "=") + if ok { + Remap[k] = v + } + } +} + type source struct { // Content The content of the source Content []byte @@ -68,8 +80,19 @@ func openFile(path string) (io.ReadCloser, bool, error) { } func loadLocal(base *source, name string) (*source, bool, error) { + var remapped bool + if !strings.HasPrefix(name, ".") { + for k, v := range Remap { + if strings.HasPrefix(name, k) { + name = v + name[len(k):] + remapped = true + break + } + } + } + filePath := name - if !filepath.IsAbs(name) { + if !remapped && !filepath.IsAbs(name) { // We want to keep all strings in / format, and only convert to platform specific when reading // This is why we use path instead of filepath. filePath = path.Join(base.Path, name) @@ -109,36 +132,6 @@ func loadLocal(base *source, name string) (*source, bool, error) { }, true, nil } -func loadProgram(data []byte, into *types.Program, targetToolName string) (types.Tool, error) { - var ext types.Program - - if err := json.Unmarshal(data[len(assemble.Header):], &ext); err != nil { - return types.Tool{}, err - } - - into.ToolSet = make(map[string]types.Tool, len(ext.ToolSet)) - for k, v := range ext.ToolSet { - if builtinTool, ok := builtin.Builtin(k); ok { - v = builtinTool - } - into.ToolSet[k] = v - } - - tool := into.ToolSet[ext.EntryToolID] - if targetToolName == "" { - return tool, nil - } - - tool, ok := into.ToolSet[tool.LocalTools[strings.ToLower(targetToolName)]] - if !ok { - return tool, &types.ErrToolNotFound{ - ToolName: targetToolName, - } - } - - return tool, nil -} - func loadOpenAPI(prg *types.Program, data []byte) *openapi3.T { var ( openAPICacheKey = hash.Digest(data) @@ -163,17 +156,25 @@ func loadOpenAPI(prg *types.Program, data []byte) *openapi3.T { return openAPIDocument } -func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base *source, targetToolName string) ([]types.Tool, error) { - data := base.Content - - if bytes.HasPrefix(data, assemble.Header) { - tool, err := loadProgram(data, prg, targetToolName) - if err != nil { - return nil, err +func processMCP(ctx context.Context, tool []types.Tool, mcpLoader MCPLoader) (result []types.Tool, _ error) { + for _, t := range tool { + if t.IsMCP() { + mcpTools, err := mcpLoader.Load(ctx, t) + if err != nil { + return nil, fmt.Errorf("error loading MCP tools: %w", err) + } + result = append(result, mcpTools...) + } else { + result = append(result, t) } - return []types.Tool{tool}, nil } + return result, nil +} + +func readTool(ctx context.Context, cache *cache.Client, mcp MCPLoader, prg *types.Program, base *source, targetToolName, defaultModel string) ([]types.Tool, error) { + data := base.Content + var ( tools []types.Tool isOpenAPI bool @@ -208,11 +209,19 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base // If we didn't get any tools from trying to parse it as OpenAPI, try to parse it as a GPTScript if len(tools) == 0 { var err error - tools, err = parser.ParseTools(bytes.NewReader(data), parser.Options{ - AssignGlobals: true, - }) - if err != nil { - return nil, err + _, marshaled, ok := strings.Cut(string(data), "#!GPTSCRIPT") + if ok { + err = json.Unmarshal([]byte(marshaled), &tools) + if err != nil { + return nil, fmt.Errorf("error parsing marshalled script: %w", err) + } + } else { + tools, err = parser.ParseTools(bytes.NewReader(data), parser.Options{ + AssignGlobals: true, + }) + if err != nil { + return nil, err + } } } @@ -220,6 +229,11 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base return nil, fmt.Errorf("no tools found in %s", base) } + tools, err := processMCP(ctx, tools, mcp) + if err != nil { + return nil, err + } + var ( localTools = types.ToolSet{} targetTools []types.Tool @@ -233,15 +247,15 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base // Probably a better way to come up with an ID tool.ID = tool.Source.Location + ":" + tool.Name - if i != 0 && tool.Parameters.Name == "" { + if i != 0 && tool.Name == "" { return nil, parser.NewErrLine(tool.Source.Location, tool.Source.LineNo, fmt.Errorf("only the first tool in a file can have no name")) } - if i != 0 && tool.Parameters.GlobalModelName != "" { + if i != 0 && tool.GlobalModelName != "" { return nil, parser.NewErrLine(tool.Source.Location, tool.Source.LineNo, fmt.Errorf("only the first tool in a file can have global model name")) } - if i != 0 && len(tool.Parameters.GlobalTools) > 0 { + if i != 0 && len(tool.GlobalTools) > 0 { return nil, parser.NewErrLine(tool.Source.Location, tool.Source.LineNo, fmt.Errorf("only the first tool in a file can have global tools")) } @@ -253,8 +267,8 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base targetTools = append(targetTools, tool) } - if targetToolName != "" && tool.Parameters.Name != "" { - if strings.EqualFold(tool.Parameters.Name, targetToolName) { + if targetToolName != "" && tool.Name != "" { + if strings.EqualFold(tool.Name, targetToolName) { targetTools = append(targetTools, tool) } else if strings.Contains(targetToolName, "*") { var patterns []string @@ -265,7 +279,7 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base } for _, pattern := range patterns { - match, err := filepath.Match(strings.ToLower(pattern), strings.ToLower(tool.Parameters.Name)) + match, err := filepath.Match(strings.ToLower(pattern), strings.ToLower(tool.Name)) if err != nil { return nil, parser.NewErrLine(tool.Source.Location, tool.Source.LineNo, err) } @@ -278,26 +292,26 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base } } - if existing, ok := localTools[strings.ToLower(tool.Parameters.Name)]; ok { + if existing, ok := localTools[strings.ToLower(tool.Name)]; ok { return nil, parser.NewErrLine(tool.Source.Location, tool.Source.LineNo, - fmt.Errorf("duplicate tool name [%s] in %s found at lines %d and %d", tool.Parameters.Name, tool.Source.Location, + fmt.Errorf("duplicate tool name [%s] in %s found at lines %d and %d", tool.Name, tool.Source.Location, tool.Source.LineNo, existing.Source.LineNo)) } - localTools[strings.ToLower(tool.Parameters.Name)] = tool + localTools[strings.ToLower(tool.Name)] = tool } - return linkAll(ctx, cache, prg, base, targetTools, localTools) + return linkAll(ctx, cache, mcp, prg, base, targetTools, localTools, defaultModel) } -func linkAll(ctx context.Context, cache *cache.Client, prg *types.Program, base *source, tools []types.Tool, localTools types.ToolSet) (result []types.Tool, _ error) { +func linkAll(ctx context.Context, cache *cache.Client, mcp MCPLoader, prg *types.Program, base *source, tools []types.Tool, localTools types.ToolSet, defaultModel string) (result []types.Tool, _ error) { localToolsMapping := make(map[string]string, len(tools)) for _, localTool := range localTools { - localToolsMapping[strings.ToLower(localTool.Parameters.Name)] = localTool.ID + localToolsMapping[strings.ToLower(localTool.Name)] = localTool.ID } for _, tool := range tools { - tool, err := link(ctx, cache, prg, base, tool, localTools, localToolsMapping) + tool, err := link(ctx, cache, mcp, prg, base, tool, localTools, localToolsMapping, defaultModel) if err != nil { return nil, err } @@ -306,7 +320,7 @@ func linkAll(ctx context.Context, cache *cache.Client, prg *types.Program, base return } -func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *source, tool types.Tool, localTools types.ToolSet, localToolsMapping map[string]string) (types.Tool, error) { +func link(ctx context.Context, cache *cache.Client, mcp MCPLoader, prg *types.Program, base *source, tool types.Tool, localTools types.ToolSet, localToolsMapping map[string]string, defaultModel string) (types.Tool, error) { if existing, ok := prg.ToolSet[tool.ID]; ok { return existing, nil } @@ -322,7 +336,7 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so // The below is done in two loops so that local names stay as the tool names // and don't get mangled by external references - for _, targetToolName := range tool.Parameters.ToolRefNames() { + for _, targetToolName := range tool.ToolRefNames() { noArgs, _ := types.SplitArg(targetToolName) localTool, ok := localTools[strings.ToLower(noArgs)] if ok { @@ -331,7 +345,7 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so linkedTool = existing } else { var err error - linkedTool, err = link(ctx, cache, prg, base, localTool, localTools, localToolsMapping) + linkedTool, err = link(ctx, cache, mcp, prg, base, localTool, localTools, localToolsMapping, defaultModel) if err != nil { return types.Tool{}, fmt.Errorf("failed linking %s at %s: %w", targetToolName, base, err) } @@ -341,7 +355,7 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so toolNames[targetToolName] = struct{}{} } else { toolName, subTool := types.SplitToolRef(targetToolName) - resolvedTools, err := resolve(ctx, cache, prg, base, toolName, subTool) + resolvedTools, err := resolve(ctx, cache, mcp, prg, base, toolName, subTool, defaultModel) if err != nil { return types.Tool{}, fmt.Errorf("failed resolving %s from %s: %w", targetToolName, base, err) } @@ -353,6 +367,10 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so tool.LocalTools = localToolsMapping + if tool.ModelName == "" { + tool.ModelName = defaultModel + } + tool = builtin.SetDefaults(tool) prg.ToolSet[tool.ID] = tool @@ -377,12 +395,12 @@ func ProgramFromSource(ctx context.Context, content, subToolName string, opts .. prg := types.Program{ ToolSet: types.ToolSet{}, } - tools, err := readTool(ctx, opt.Cache, &prg, &source{ + tools, err := readTool(ctx, opt.Cache, opt.MCPLoader, &prg, &source{ Content: []byte(content), Path: locationPath, Name: locationName, Location: opt.Location, - }, subToolName) + }, subToolName, opt.DefaultModel) if err != nil { return types.Program{}, err } @@ -391,20 +409,37 @@ func ProgramFromSource(ctx context.Context, content, subToolName string, opts .. } type Options struct { - Cache *cache.Client - Location string + Cache *cache.Client + Location string + DefaultModel string + MCPLoader MCPLoader +} + +type MCPLoader interface { + Load(ctx context.Context, tool types.Tool) ([]types.Tool, error) + Close() error } func complete(opts ...Options) (result Options) { for _, opt := range opts { result.Cache = types.FirstSet(opt.Cache, result.Cache) result.Location = types.FirstSet(opt.Location, result.Location) + result.DefaultModel = types.FirstSet(opt.DefaultModel, result.DefaultModel) + result.MCPLoader = types.FirstSet(opt.MCPLoader, result.MCPLoader) } if result.Location == "" { result.Location = "inline" } + if result.DefaultModel == "" { + result.DefaultModel = builtin.GetDefaultModel() + } + + if result.MCPLoader == nil { + result.MCPLoader = mcp.DefaultLoader + } + return } @@ -428,7 +463,7 @@ func Program(ctx context.Context, name, subToolName string, opts ...Options) (ty Name: name, ToolSet: types.ToolSet{}, } - tools, err := resolve(ctx, opt.Cache, &prg, &source{}, name, subToolName) + tools, err := resolve(ctx, opt.Cache, opt.MCPLoader, &prg, &source{}, name, subToolName, opt.DefaultModel) if err != nil { return types.Program{}, err } @@ -436,9 +471,9 @@ func Program(ctx context.Context, name, subToolName string, opts ...Options) (ty return prg, nil } -func resolve(ctx context.Context, cache *cache.Client, prg *types.Program, base *source, name, subTool string) ([]types.Tool, error) { +func resolve(ctx context.Context, cache *cache.Client, mcp MCPLoader, prg *types.Program, base *source, name, subTool, defaultModel string) ([]types.Tool, error) { if subTool == "" { - t, ok := builtin.Builtin(name) + t, ok := builtin.DefaultModel(name, defaultModel) if ok { prg.ToolSet[t.ID] = t return []types.Tool{t}, nil @@ -450,7 +485,7 @@ func resolve(ctx context.Context, cache *cache.Client, prg *types.Program, base return nil, err } - result, err := readTool(ctx, cache, prg, s, subTool) + result, err := readTool(ctx, cache, mcp, prg, s, subTool, defaultModel) if err != nil { return nil, err } diff --git a/pkg/loader/loader_test.go b/pkg/loader/loader_test.go index 7c480034..a39c2df9 100644 --- a/pkg/loader/loader_test.go +++ b/pkg/loader/loader_test.go @@ -131,13 +131,13 @@ func TestHelloWorld(t *testing.T) { "modelName": "gpt-4o", "internalPrompt": null, "arguments": { + "type": "object", "properties": { "input": { - "description": "Any string", - "type": "string" + "type": "string", + "description": "Any string" } - }, - "type": "object" + } }, "instructions": "echo \"${input}\"", "id": "https://get.gptscript.ai/echo.gpt:", diff --git a/pkg/loader/openapi.go b/pkg/loader/openapi.go index e62fc5ef..ce8c5dc6 100644 --- a/pkg/loader/openapi.go +++ b/pkg/loader/openapi.go @@ -14,6 +14,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/gptscript-ai/gptscript/pkg/openapi" "github.com/gptscript-ai/gptscript/pkg/types" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) var toolNameRegex = regexp.MustCompile(`[^a-zA-Z0-9_-]+`) @@ -150,10 +151,9 @@ func getOpenAPITools(t *openapi3.T, defaultHost, source, targetToolName string) Parameters: types.Parameters{ Name: toolName, Description: toolDesc, - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{}, - Required: []string{}, + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: make(map[string]*jsonschema.Schema), }, }, }, @@ -174,11 +174,11 @@ func getOpenAPITools(t *openapi3.T, defaultHost, source, targetToolName string) } // Add the new arg to the tool's arguments - tool.Parameters.Arguments.Properties[param.Value.Name] = &openapi3.SchemaRef{Value: arg} + tool.Arguments.Properties[param.Value.Name] = openAPI3SchemaToJSONSchema(arg) // Check whether it is required if param.Value.Required { - tool.Parameters.Arguments.Required = append(tool.Parameters.Arguments.Required, param.Value.Name) + tool.Arguments.Required = append(tool.Arguments.Required, param.Value.Name) } // Add the parameter to the appropriate list for the tool's instructions @@ -227,7 +227,7 @@ func getOpenAPITools(t *openapi3.T, defaultHost, source, targetToolName string) } // Unfortunately, the request body doesn't contain any good descriptor for it, // so we just use "requestBodyContent" as the name of the arg. - tool.Parameters.Arguments.Properties["requestBodyContent"] = &openapi3.SchemaRef{Value: arg} + tool.Arguments.Properties["requestBodyContent"] = openAPI3SchemaToJSONSchema(arg) break } @@ -310,7 +310,7 @@ func getOpenAPITools(t *openapi3.T, defaultHost, source, targetToolName string) } // Register - toolNames = append(toolNames, tool.Parameters.Name) + toolNames = append(toolNames, tool.Name) tools = append(tools, tool) operationNum++ } @@ -373,6 +373,152 @@ func parseServer(server *openapi3.Server) (string, error) { return s, nil } +// openAPI3SchemaToJSONSchema converts an openapi3.Schema to a jsonschema.Schema +func openAPI3SchemaToJSONSchema(schema *openapi3.Schema) *jsonschema.Schema { + if schema == nil { + return nil + } + + result := &jsonschema.Schema{ + Title: schema.Title, + Description: schema.Description, + Format: schema.Format, + } + + // Convert type + if schema.Type != nil && len(*schema.Type) > 0 { + result.Types = *schema.Type + } + + // In OpenAPI v3.0, there is a nullable field. + // In OpenAPI v3.1, nullable is specified by providing a separate type. + if schema.Nullable && !slices.Contains(result.Types, "null") { + result.Types = append(result.Types, "null") + } + + // Convert enum + if schema.Enum != nil { + result.Enum = schema.Enum + } + + // Convert min/max + if schema.Min != nil { + minVal := *schema.Min + result.Minimum = &minVal + + // In OpenAPI 3, ExclusiveMin is a boolean flag that applies to Min + // In OpenAPI 3.1, ExclusiveMinimum is a separate value + if schema.ExclusiveMin { + result.ExclusiveMinimum = &minVal + } + } + if schema.Max != nil { + maxVal := *schema.Max + result.Maximum = &maxVal + + // In OpenAPI 3, ExclusiveMax is a boolean flag that applies to Max + // In OpenAPI 3.1, ExclusiveMaximum is a separate value + if schema.ExclusiveMax { + result.ExclusiveMaximum = &maxVal + } + } + + // Convert minLength/maxLength + if schema.MinLength != 0 { + minLength := int(schema.MinLength) + result.MinLength = &minLength + } + if schema.MaxLength != nil { + maxLength := int(*schema.MaxLength) + result.MaxLength = &maxLength + } + + // Convert pattern + if schema.Pattern != "" { + result.Pattern = schema.Pattern + } + + // Convert minItems/maxItems + if schema.MinItems != 0 { + minItems := int(schema.MinItems) + result.MinItems = &minItems + } + if schema.MaxItems != nil { + maxItems := int(*schema.MaxItems) + result.MaxItems = &maxItems + } + + // Convert uniqueItems + result.UniqueItems = schema.UniqueItems + + // Convert minProperties/maxProperties + if schema.MinProps != 0 { + minProps := int(schema.MinProps) + result.MinProperties = &minProps + } + if schema.MaxProps != nil { + maxProps := int(*schema.MaxProps) + result.MaxProperties = &maxProps + } + + // Convert required + if schema.Required != nil { + result.Required = schema.Required + } + + // Convert properties + if schema.Properties != nil { + result.Properties = make(map[string]*jsonschema.Schema, len(schema.Properties)) + for name, propRef := range schema.Properties { + if propRef != nil && propRef.Value != nil { + result.Properties[name] = openAPI3SchemaToJSONSchema(propRef.Value) + } + } + } + + // Convert items + if schema.Items != nil && schema.Items.Value != nil { + result.Items = openAPI3SchemaToJSONSchema(schema.Items.Value) + } + + // Convert oneOf + if schema.OneOf != nil { + result.OneOf = make([]*jsonschema.Schema, len(schema.OneOf)) + for i, oneOfRef := range schema.OneOf { + if oneOfRef != nil && oneOfRef.Value != nil { + result.OneOf[i] = openAPI3SchemaToJSONSchema(oneOfRef.Value) + } + } + } + + // Convert anyOf + if schema.AnyOf != nil { + result.AnyOf = make([]*jsonschema.Schema, len(schema.AnyOf)) + for i, anyOfRef := range schema.AnyOf { + if anyOfRef != nil && anyOfRef.Value != nil { + result.AnyOf[i] = openAPI3SchemaToJSONSchema(anyOfRef.Value) + } + } + } + + // Convert allOf + if schema.AllOf != nil { + result.AllOf = make([]*jsonschema.Schema, len(schema.AllOf)) + for i, allOfRef := range schema.AllOf { + if allOfRef != nil && allOfRef.Value != nil { + result.AllOf[i] = openAPI3SchemaToJSONSchema(allOfRef.Value) + } + } + } + + // Convert not + if schema.Not != nil && schema.Not.Value != nil { + result.Not = openAPI3SchemaToJSONSchema(schema.Not.Value) + } + + return result +} + func getOpenAPIToolsRevamp(t *openapi3.T, source, targetToolName string) ([]types.Tool, error) { if t == nil { return nil, fmt.Errorf("OpenAPI spec is nil") @@ -402,16 +548,14 @@ func getOpenAPIToolsRevamp(t *openapi3.T, source, targetToolName string) ([]type Parameters: types.Parameters{ Name: types.ToolNormalizer("get-schema-" + t.Info.Title), Description: fmt.Sprintf("Get the JSONSchema for the arguments for an operation for %s. You must do this before you run the operation.", t.Info.Title), - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{openapi3.TypeObject}, - Properties: openapi3.Schemas{ + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ "operation": { - Value: &openapi3.Schema{ - Type: &openapi3.Types{openapi3.TypeString}, - Title: "operation", - Description: "the name of the operation to get the schema for", - Required: []string{"operation"}, - }, + Type: "string", + Title: "operation", + Description: "the name of the operation to get the schema for", + Required: []string{"operation"}, }, }, }, @@ -428,24 +572,20 @@ func getOpenAPIToolsRevamp(t *openapi3.T, source, targetToolName string) ([]type Parameters: types.Parameters{ Name: types.ToolNormalizer("run-operation-" + t.Info.Title), Description: fmt.Sprintf("Run an operation for %s. You MUST call %s for the operation before you use this tool.", t.Info.Title, openapi.GetSchemaTool), - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{openapi3.TypeObject}, - Properties: openapi3.Schemas{ + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ "operation": { - Value: &openapi3.Schema{ - Type: &openapi3.Types{openapi3.TypeString}, - Title: "operation", - Description: "the name of the operation to run", - Required: []string{"operation"}, - }, + Type: "string", + Title: "operation", + Description: "the name of the operation to run", + Required: []string{"operation"}, }, "args": { - Value: &openapi3.Schema{ - Type: &openapi3.Types{openapi3.TypeString}, - Title: "args", - Description: "the JSON string containing arguments; must match the JSONSchema for the operation", - Required: []string{"args"}, - }, + Type: "string", + Title: "args", + Description: "the JSON string containing arguments; must match the JSONSchema for the operation", + Required: []string{"args"}, }, }, }, @@ -457,7 +597,7 @@ func getOpenAPIToolsRevamp(t *openapi3.T, source, targetToolName string) ([]type exportTool := types.Tool{ ToolDef: types.ToolDef{ Parameters: types.Parameters{ - Export: []string{list.Parameters.Name, getSchema.Parameters.Name, run.Parameters.Name}, + Export: []string{list.Name, getSchema.Name, run.Name}, }, }, } diff --git a/pkg/loader/openapi_test.go b/pkg/loader/openapi_test.go index 1a7eaa76..594d8cf7 100644 --- a/pkg/loader/openapi_test.go +++ b/pkg/loader/openapi_test.go @@ -26,7 +26,7 @@ func TestLoadOpenAPI(t *testing.T) { } datav3, err := os.ReadFile("testdata/openapi_v3.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv3, &source{Content: datav3}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv3, &source{Content: datav3}, "", "") require.NoError(t, err, "failed to read openapi v3") require.Equal(t, 3, numOpenAPITools(prgv3.ToolSet), "expected 3 openapi tools") @@ -35,7 +35,7 @@ func TestLoadOpenAPI(t *testing.T) { } datav2, err := os.ReadFile("testdata/openapi_v2.json") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv2json, &source{Content: datav2}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv2json, &source{Content: datav2}, "", "") require.NoError(t, err, "failed to read openapi v2") require.Equal(t, 3, numOpenAPITools(prgv2json.ToolSet), "expected 3 openapi tools") @@ -44,7 +44,7 @@ func TestLoadOpenAPI(t *testing.T) { } datav2, err = os.ReadFile("testdata/openapi_v2.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv2yaml, &source{Content: datav2}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv2yaml, &source{Content: datav2}, "", "") require.NoError(t, err, "failed to read openapi v2 (yaml)") require.Equal(t, 3, numOpenAPITools(prgv2yaml.ToolSet), "expected 3 openapi tools") @@ -57,7 +57,7 @@ func TestOpenAPIv3(t *testing.T) { } datav3, err := os.ReadFile("testdata/openapi_v3.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv3, &source{Content: datav3}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv3, &source{Content: datav3}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv3.ToolSet, autogold.Dir("testdata/openapi")) @@ -69,7 +69,7 @@ func TestOpenAPIv3NoOperationIDs(t *testing.T) { } datav3, err := os.ReadFile("testdata/openapi_v3_no_operation_ids.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv3, &source{Content: datav3}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv3, &source{Content: datav3}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv3.ToolSet, autogold.Dir("testdata/openapi")) @@ -81,7 +81,7 @@ func TestOpenAPIv2(t *testing.T) { } datav2, err := os.ReadFile("testdata/openapi_v2.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv2, &source{Content: datav2}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv2, &source{Content: datav2}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv2.ToolSet, autogold.Dir("testdata/openapi")) @@ -94,7 +94,7 @@ func TestOpenAPIv3Revamp(t *testing.T) { } datav3, err := os.ReadFile("testdata/openapi_v3.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv3, &source{Content: datav3}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv3, &source{Content: datav3}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv3.ToolSet, autogold.Dir("testdata/openapi")) @@ -107,7 +107,7 @@ func TestOpenAPIv3NoOperationIDsRevamp(t *testing.T) { } datav3, err := os.ReadFile("testdata/openapi_v3_no_operation_ids.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv3, &source{Content: datav3}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv3, &source{Content: datav3}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv3.ToolSet, autogold.Dir("testdata/openapi")) @@ -120,8 +120,18 @@ func TestOpenAPIv2Revamp(t *testing.T) { } datav2, err := os.ReadFile("testdata/openapi_v2.yaml") require.NoError(t, err) - _, err = readTool(context.Background(), nil, &prgv2, &source{Content: datav2}, "") + _, err = readTool(context.Background(), nil, fakeMCPLoader{}, &prgv2, &source{Content: datav2}, "", "") require.NoError(t, err) autogold.ExpectFile(t, prgv2.ToolSet, autogold.Dir("testdata/openapi")) } + +type fakeMCPLoader struct{} + +func (fakeMCPLoader) Load(context.Context, types.Tool) ([]types.Tool, error) { + return nil, nil +} + +func (fakeMCPLoader) Close() error { + return nil +} diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv2.golden b/pkg/loader/testdata/openapi/TestOpenAPIv2.golden index 39b0b2c1..ebf29cb4 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv2.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv2.golden @@ -56,16 +56,19 @@ types.ToolSet{ Name: "listPets", Description: "List all pets", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "limit": { + Description: "How many items to return at one time (max 100)", + Types: []string{ + "integer", + }, + Properties: map[string]*jsonschema.Schema{}, + AllOf: []*jsonschema.Schema{}, + Format: "int32", + }, }, - Required: []string{}, - Properties: openapi3.Schemas{"limit": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"integer"}, - Format: "int32", - Description: "How many items to return at one time (max 100)", - }}}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":[{"name":"limit","style":"","explode":null}],"pathParameters":null,"headerParameters":null,"cookieParameters":null}'`, @@ -86,13 +89,15 @@ types.ToolSet{ Name: "showPetById", Description: "Info for a specific pet", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, + Arguments: &jsonschema.Schema{ + Type: "object", Required: []string{"petId"}, - Properties: openapi3.Schemas{"petId": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Properties: map[string]*jsonschema.Schema{"petId": { Description: "The id of the pet to retrieve", - }}}, + Types: []string{"string"}, + Properties: map[string]*jsonschema.Schema{}, + AllOf: []*jsonschema.Schema{}, + }}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets/{petId}","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":null,"pathParameters":[{"name":"petId","style":"","explode":null}],"headerParameters":null,"cookieParameters":null}'`, diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv2Revamp.golden b/pkg/loader/testdata/openapi/TestOpenAPIv2Revamp.golden index ebe68cc2..ac32cc58 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv2Revamp.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv2Revamp.golden @@ -36,16 +36,18 @@ types.ToolSet{ Name: "getSchemaSwaggerPetstore", Description: "Get the JSONSchema for the arguments for an operation for Swagger Petstore. You must do this before you run the operation.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "operation": { + Title: "operation", + Description: "the name of the operation to get the schema for", + Type: "string", + Required: []string{ + "operation", + }, + }, }, - Properties: openapi3.Schemas{"operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, - Title: "operation", - Description: "the name of the operation to get the schema for", - Required: []string{"operation"}, - }}}, }, }, Instructions: "#!sys.openapi get-schema ", @@ -84,21 +86,21 @@ types.ToolSet{ Name: "runOperationSwaggerPetstore", Description: "Run an operation for Swagger Petstore. You MUST call get-schema for the operation before you use this tool.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{ - "args": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "args": { Title: "args", Description: "the JSON string containing arguments; must match the JSONSchema for the operation", + Type: "string", Required: []string{"args"}, - }}, - "operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + }, + "operation": { Title: "operation", Description: "the name of the operation to run", + Type: "string", Required: []string{"operation"}, - }}, + }, }, }, }, diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv3.golden b/pkg/loader/testdata/openapi/TestOpenAPIv3.golden index 37ac2fe2..7e4a7993 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv3.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv3.golden @@ -37,30 +37,29 @@ types.ToolSet{ Name: "createPets", Description: "Create a pet", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", - }, - Required: []string{}, - Properties: openapi3.Schemas{"requestBodyContent": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Required: []string{ - "id", - "name", - }, - Properties: openapi3.Schemas{ - "id": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: &openapi3.Types{ + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "requestBodyContent": { + Types: []string{ + "object", + }, + Required: []string{ + "id", + "name", + }, + Properties: map[string]*jsonschema.Schema{ + "id": { + Types: []string{ "integer", }, Format: "int64", }, + "name": {Types: []string{"string"}}, + "tag": {Types: []string{"string"}}, }, - "name": &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"string"}}}, - "tag": &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"string"}}}, }, - }}}, + }, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets","method":"POST","bodyContentMIME":"application/json","securityInfos":null,"queryParameters":null,"pathParameters":null,"headerParameters":null,"cookieParameters":null}'`, @@ -81,15 +80,14 @@ types.ToolSet{ Name: "listPets", Description: "List all pets", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Required: []string{}, - Properties: openapi3.Schemas{"limit": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"integer"}, - Format: "int32", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{"limit": { Description: "How many items to return at one time (max 100)", - Max: valast.Ptr(float64(100)), - }}}, + Types: []string{"integer"}, + Maximum: valast.Ptr(float64(100)), + Format: "int32", + }}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":[{"name":"limit","style":"","explode":null}],"pathParameters":null,"headerParameters":null,"cookieParameters":null}'`, @@ -110,13 +108,13 @@ types.ToolSet{ Name: "showPetById", Description: "Info for a specific pet", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, + Arguments: &jsonschema.Schema{ + Type: "object", Required: []string{"petId"}, - Properties: openapi3.Schemas{"petId": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Properties: map[string]*jsonschema.Schema{"petId": { Description: "The id of the pet to retrieve", - }}}, + Types: []string{"string"}, + }}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets/{petId}","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":null,"pathParameters":[{"name":"petId","style":"","explode":null}],"headerParameters":null,"cookieParameters":null}'`, diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDs.golden b/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDs.golden index e950e19c..5ebd8aa9 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDs.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDs.golden @@ -37,17 +37,18 @@ types.ToolSet{ Name: "get_pets", Description: "List all pets", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "limit": { + Description: "How many items to return at one time (max 100)", + Types: []string{ + "integer", + }, + Maximum: valast.Ptr(float64(100)), + Format: "int32", + }, }, - Required: []string{}, - Properties: openapi3.Schemas{"limit": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"integer"}, - Format: "int32", - Description: "How many items to return at one time (max 100)", - Max: valast.Ptr(float64(100)), - }}}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":[{"name":"limit","style":"","explode":null}],"pathParameters":null,"headerParameters":null,"cookieParameters":null}'`, @@ -68,13 +69,13 @@ types.ToolSet{ Name: "get_pets_petId", Description: "Info for a specific pet", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, + Arguments: &jsonschema.Schema{ + Type: "object", Required: []string{"petId"}, - Properties: openapi3.Schemas{"petId": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Properties: map[string]*jsonschema.Schema{"petId": { Description: "The id of the pet to retrieve", - }}}, + Types: []string{"string"}, + }}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets/{petId}","method":"GET","bodyContentMIME":"","securityInfos":null,"queryParameters":null,"pathParameters":[{"name":"petId","style":"","explode":null}],"headerParameters":null,"cookieParameters":null}'`, @@ -95,28 +96,25 @@ types.ToolSet{ Name: "post_pets", Description: "Create a pet", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Required: []string{}, - Properties: openapi3.Schemas{"requestBodyContent": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{"requestBodyContent": { + Types: []string{"object"}, Required: []string{ "id", "name", }, - Properties: openapi3.Schemas{ - "id": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: &openapi3.Types{ - "integer", - }, - Format: "int64", + Properties: map[string]*jsonschema.Schema{ + "id": { + Types: []string{ + "integer", }, + Format: "int64", }, - "name": &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"string"}}}, - "tag": &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"string"}}}, + "name": {Types: []string{"string"}}, + "tag": {Types: []string{"string"}}, }, - }}}, + }}, }, }, Instructions: `#!sys.openapi '{"server":"http://petstore.swagger.io/v1","path":"/pets","method":"POST","bodyContentMIME":"application/json","securityInfos":null,"queryParameters":null,"pathParameters":null,"headerParameters":null,"cookieParameters":null}'`, diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDsRevamp.golden b/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDsRevamp.golden index ebe68cc2..ac32cc58 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDsRevamp.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv3NoOperationIDsRevamp.golden @@ -36,16 +36,18 @@ types.ToolSet{ Name: "getSchemaSwaggerPetstore", Description: "Get the JSONSchema for the arguments for an operation for Swagger Petstore. You must do this before you run the operation.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "operation": { + Title: "operation", + Description: "the name of the operation to get the schema for", + Type: "string", + Required: []string{ + "operation", + }, + }, }, - Properties: openapi3.Schemas{"operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, - Title: "operation", - Description: "the name of the operation to get the schema for", - Required: []string{"operation"}, - }}}, }, }, Instructions: "#!sys.openapi get-schema ", @@ -84,21 +86,21 @@ types.ToolSet{ Name: "runOperationSwaggerPetstore", Description: "Run an operation for Swagger Petstore. You MUST call get-schema for the operation before you use this tool.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{ - "args": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "args": { Title: "args", Description: "the JSON string containing arguments; must match the JSONSchema for the operation", + Type: "string", Required: []string{"args"}, - }}, - "operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + }, + "operation": { Title: "operation", Description: "the name of the operation to run", + Type: "string", Required: []string{"operation"}, - }}, + }, }, }, }, diff --git a/pkg/loader/testdata/openapi/TestOpenAPIv3Revamp.golden b/pkg/loader/testdata/openapi/TestOpenAPIv3Revamp.golden index ebe68cc2..ac32cc58 100644 --- a/pkg/loader/testdata/openapi/TestOpenAPIv3Revamp.golden +++ b/pkg/loader/testdata/openapi/TestOpenAPIv3Revamp.golden @@ -36,16 +36,18 @@ types.ToolSet{ Name: "getSchemaSwaggerPetstore", Description: "Get the JSONSchema for the arguments for an operation for Swagger Petstore. You must do this before you run the operation.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{ - "object", + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "operation": { + Title: "operation", + Description: "the name of the operation to get the schema for", + Type: "string", + Required: []string{ + "operation", + }, + }, }, - Properties: openapi3.Schemas{"operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, - Title: "operation", - Description: "the name of the operation to get the schema for", - Required: []string{"operation"}, - }}}, }, }, Instructions: "#!sys.openapi get-schema ", @@ -84,21 +86,21 @@ types.ToolSet{ Name: "runOperationSwaggerPetstore", Description: "Run an operation for Swagger Petstore. You MUST call get-schema for the operation before you use this tool.", ModelName: "gpt-4o", - Arguments: &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{ - "args": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + Arguments: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "args": { Title: "args", Description: "the JSON string containing arguments; must match the JSONSchema for the operation", + Type: "string", Required: []string{"args"}, - }}, - "operation": &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: &openapi3.Types{"string"}, + }, + "operation": { Title: "operation", Description: "the name of the operation to run", + Type: "string", Required: []string{"operation"}, - }}, + }, }, }, }, diff --git a/pkg/loader/url.go b/pkg/loader/url.go index 72970546..d84e08be 100644 --- a/pkg/loader/url.go +++ b/pkg/loader/url.go @@ -63,6 +63,9 @@ func loadURL(ctx context.Context, cache *cache.Client, base *source, name string } } } + if cachedKey.Path == "" { + cachedKey.Path = "." + } if ok, err := cache.Get(ctx, cachedKey, &cachedValue); err != nil { return nil, false, err diff --git a/pkg/mcp/client.go b/pkg/mcp/client.go new file mode 100644 index 00000000..a6563bd2 --- /dev/null +++ b/pkg/mcp/client.go @@ -0,0 +1,26 @@ +package mcp + +import ( + nmcp "github.com/nanobot-ai/nanobot/pkg/mcp" +) + +func (l *Local) Client(server ServerConfig, clientOpts ...nmcp.ClientOption) (*Client, error) { + session, err := l.loadSession(server, "default", clientOpts...) + if err != nil { + return nil, err + } + + return &Client{ + Client: session.Client, + ID: session.ID, + }, nil +} + +type Client struct { + *nmcp.Client + ID string +} + +func (c *Client) Capabilities() nmcp.ServerCapabilities { + return c.Session.InitializeResult.Capabilities +} diff --git a/pkg/mcp/loader.go b/pkg/mcp/loader.go new file mode 100644 index 00000000..7ec6fb5c --- /dev/null +++ b/pkg/mcp/loader.go @@ -0,0 +1,333 @@ +package mcp + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "maps" + "slices" + "strings" + "sync" + + "github.com/gptscript-ai/gptscript/pkg/hash" + "github.com/gptscript-ai/gptscript/pkg/mvl" + "github.com/gptscript-ai/gptscript/pkg/types" + "github.com/modelcontextprotocol/go-sdk/jsonschema" + nmcp "github.com/nanobot-ai/nanobot/pkg/mcp" +) + +var ( + DefaultLoader = &Local{} + DefaultRunner = DefaultLoader + + logger = mvl.Package() +) + +type Local struct { + lock sync.Mutex + sessions map[string]*Session + sessionCtx context.Context + cancel context.CancelFunc +} + +type Session struct { + ID string + Client *nmcp.Client + Config ServerConfig +} + +type Config struct { + MCPServers map[string]ServerConfig `json:"mcpServers"` +} + +// ServerConfig represents an MCP server configuration for tools calls. +// It is important that this type doesn't have any maps. +type ServerConfig struct { + DisableInstruction bool `json:"disableInstruction"` + Command string `json:"command"` + Args []string `json:"args"` + Env []string `json:"env"` + Server string `json:"server"` + URL string `json:"url"` + BaseURL string `json:"baseURL,omitempty"` + Headers []string `json:"headers"` + Scope string `json:"scope"` + AllowedTools []string `json:"allowedTools"` +} + +func (s *ServerConfig) GetBaseURL() string { + if s.BaseURL != "" { + return s.BaseURL + } + if s.Server != "" { + return s.Server + } + return s.URL +} + +func (l *Local) Load(ctx context.Context, tool types.Tool) (result []types.Tool, _ error) { + if !tool.IsMCP() { + return nil, nil + } + + _, configData, _ := strings.Cut(tool.Instructions, "\n") + + var servers Config + if err := json.Unmarshal([]byte(strings.TrimSpace(configData)), &servers); err != nil { + return nil, fmt.Errorf("failed to parse MCP configuration: %w\n%s", err, configData) + } + + if len(servers.MCPServers) == 0 { + // Try to load just one server + var server ServerConfig + if err := json.Unmarshal([]byte(strings.TrimSpace(configData)), &server); err != nil { + return nil, fmt.Errorf("failed to parse single MCP server configuration: %w\n%s", err, configData) + } + if server.Command == "" && server.URL == "" && server.Server == "" { + return nil, fmt.Errorf("no MCP server configuration found in tool instructions: %s", configData) + } + servers.MCPServers = map[string]ServerConfig{ + "default": server, + } + } + + if len(servers.MCPServers) > 1 { + return nil, fmt.Errorf("only a single MCP server definition is supported") + } + + for server := range maps.Keys(servers.MCPServers) { + tools, err := l.LoadTools(ctx, servers.MCPServers[server], server, tool.Name) + if err != nil { + return nil, fmt.Errorf("failed to load MCP session for server %s: %w", server, err) + } + + return tools, nil + } + + // This should never happen, but just in case + return nil, fmt.Errorf("no MCP server configuration found in tool instructions: %s", configData) +} + +func (l *Local) LoadTools(ctx context.Context, server ServerConfig, serverName, toolName string) ([]types.Tool, error) { + allowedTools := server.AllowedTools + // Reset so we don't start a new MCP server, no reason to if one is already running and the allowed tools change. + server.AllowedTools = nil + + session, err := l.loadSession(server, serverName) + if err != nil { + return nil, err + } + + return l.sessionToTools(ctx, session, toolName, allowedTools) +} + +func (l *Local) ShutdownServer(server ServerConfig) error { + if l == nil { + return nil + } + + id := hash.Digest(server) + + l.lock.Lock() + + if l.sessionCtx == nil { + l.lock.Unlock() + return nil + } + + session := l.sessions[id] + delete(l.sessions, id) + + l.lock.Unlock() + + if session != nil && session.Client != nil { + session.Client.Session.Close(true) + session.Client.Session.Wait() + } + + return nil +} + +func (l *Local) Close() error { + if l == nil { + return nil + } + + l.lock.Lock() + defer l.lock.Unlock() + + if l.sessionCtx == nil { + return nil + } + + defer func() { + l.cancel() + l.sessionCtx = nil + }() + + var errs []error + for id, session := range l.sessions { + logger.Infof("closing MCP session %s", id) + session.Client.Session.Close(false) + session.Client.Session.Wait() + } + + return errors.Join(errs...) +} + +func (l *Local) sessionToTools(ctx context.Context, session *Session, toolName string, allowedTools []string) ([]types.Tool, error) { + allToolsAllowed := allowedTools == nil || slices.Contains(allowedTools, "*") + + tools, err := session.Client.ListTools(ctx) + if err != nil { + return nil, fmt.Errorf("failed to list tools: %w", err) + } + + toolDefs := []types.Tool{{ /* this is a placeholder for main tool */ }} + var toolNames []string + + for _, tool := range tools.Tools { + if !allToolsAllowed && !slices.Contains(allowedTools, tool.Name) { + continue + } + if tool.Name == "" { + // I dunno, bad tool? + continue + } + + var schema jsonschema.Schema + + schemaData, err := json.Marshal(tool.InputSchema) + if err != nil { + panic(err) + } + + if err := json.Unmarshal(schemaData, &schema); err != nil { + return nil, fmt.Errorf("failed to unmarshal tool input schema: %w", err) + } + + annotations, err := json.Marshal(tool.Annotations) + if err != nil { + return nil, fmt.Errorf("failed to marshal tool annotations: %w", err) + } + + toolDef := types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: tool.Name, + Description: tool.Description, + Arguments: &schema, + }, + Instructions: types.MCPInvokePrefix + tool.Name + " " + session.ID, + }, + } + + if string(annotations) != "{}" && string(annotations) != "null" { + toolDef.MetaData = map[string]string{ + "mcp-tool-annotations": string(annotations), + } + } + + if tool.Annotations != nil && tool.Annotations.Title != "" && !slices.Contains(strings.Fields(tool.Annotations.Title), "as") { + toolNames = append(toolNames, tool.Name+" as "+tool.Annotations.Title) + } else { + toolNames = append(toolNames, tool.Name) + } + + toolDefs = append(toolDefs, toolDef) + } + + main := types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: toolName, + Description: session.Client.Session.InitializeResult.ServerInfo.Name, + Export: toolNames, + }, + MetaData: map[string]string{ + "bundle": "true", + }, + }, + } + + if session.Client.Session.InitializeResult.Instructions != "" { + data, _ := json.Marshal(map[string]any{ + "tools": toolNames, + "instructions": session.Client.Session.InitializeResult.Instructions, + }) + toolDefs = append(toolDefs, types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: session.ID, + Type: "context", + }, + Instructions: types.EchoPrefix + "\n" + `# START MCP SERVER INFO: ` + session.Client.Session.InitializeResult.ServerInfo.Name + "\n" + + `You have available the following tools from an MCP Server that has provided the following additional instructions` + "\n" + + string(data) + "\n" + + `# END MCP SERVER INFO` + "\n", + }, + }) + + main.ExportContext = append(main.ExportContext, session.ID) + } + + toolDefs[0] = main + return toolDefs, nil +} + +func (l *Local) loadSession(server ServerConfig, serverName string, clientOpts ...nmcp.ClientOption) (*Session, error) { + id := hash.Digest(server) + l.lock.Lock() + existing, ok := l.sessions[id] + if l.sessionCtx == nil { + l.sessionCtx, l.cancel = context.WithCancel(context.Background()) + } + l.lock.Unlock() + + if ok { + return existing, nil + } + + c, err := nmcp.NewClient(l.sessionCtx, serverName, nmcp.Server{ + Env: splitIntoMap(server.Env), + Command: server.Command, + Args: server.Args, + BaseURL: server.GetBaseURL(), + Headers: splitIntoMap(server.Headers), + }, clientOpts...) + if err != nil { + return nil, fmt.Errorf("failed to create MCP client: %w", err) + } + + result := &Session{ + ID: id, + Client: c, + Config: server, + } + + l.lock.Lock() + defer l.lock.Unlock() + + if existing, ok = l.sessions[id]; ok { + c.Session.Close(true) + return existing, nil + } + + if l.sessions == nil { + l.sessions = make(map[string]*Session, 1) + } + l.sessions[id] = result + return result, nil +} + +func splitIntoMap(list []string) map[string]string { + result := make(map[string]string, len(list)) + for _, s := range list { + k, v, ok := strings.Cut(s, "=") + if ok { + result[k] = v + } + } + return result +} diff --git a/pkg/mcp/runner.go b/pkg/mcp/runner.go new file mode 100644 index 00000000..37032392 --- /dev/null +++ b/pkg/mcp/runner.go @@ -0,0 +1,58 @@ +package mcp + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/gptscript-ai/gptscript/pkg/engine" + "github.com/gptscript-ai/gptscript/pkg/types" +) + +func (l *Local) Run(ctx engine.Context, _ chan<- types.CompletionStatus, tool types.Tool, input string) (string, error) { + fields := strings.Fields(tool.Instructions) + if len(fields) < 2 { + return "", fmt.Errorf("invalid mcp call, invalid number of fields in %s", tool.Instructions) + } + + id := fields[1] + toolName, ok := strings.CutPrefix(fields[0], types.MCPInvokePrefix) + if !ok { + return "", fmt.Errorf("invalid mcp call, invalid tool name in %s", tool.Instructions) + } + + arguments := map[string]any{} + + if input != "" { + if err := json.Unmarshal([]byte(input), &arguments); err != nil { + return "", fmt.Errorf("failed to unmarshal input: %w", err) + } + } + + l.lock.Lock() + session, ok := l.sessions[id] + l.lock.Unlock() + if !ok { + return "", fmt.Errorf("session not found for MCP server %s", id) + } + + result, err := session.Client.Call(ctx.Ctx, toolName, arguments) + if err != nil { + if ctx.ToolCategory == engine.NoCategory && ctx.Parent != nil { + var output []byte + if result != nil { + output, _ = json.Marshal(result) + } + // If this is a sub-call, then don't return the error; return the error as a message so that the LLM can retry. + return fmt.Sprintf("ERROR: got (%v) while running tool, OUTPUT: %s", err, string(output)), nil + } + return "", fmt.Errorf("failed to call tool %s: %w", toolName, err) + } + + str, err := json.Marshal(result) + if err != nil { + return "", fmt.Errorf("failed to marshal result: %w", err) + } + + return string(str), nil +} diff --git a/pkg/monitor/display.go b/pkg/monitor/display.go index 73a15006..6bc6e9f3 100644 --- a/pkg/monitor/display.go +++ b/pkg/monitor/display.go @@ -386,7 +386,7 @@ func (c callName) String() string { for { tool := c.prg.ToolSet[currentCall.ToolID] - name := tool.Parameters.Name + name := tool.Name if name == "" { name = tool.Source.Location } diff --git a/pkg/openai/client.go b/pkg/openai/client.go index 61a7ec77..1a2f0968 100644 --- a/pkg/openai/client.go +++ b/pkg/openai/client.go @@ -9,12 +9,13 @@ import ( "slices" "sort" "strings" + "time" openai "github.com/gptscript-ai/chat-completion-client" "github.com/gptscript-ai/gptscript/pkg/cache" - gcontext "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/counter" "github.com/gptscript-ai/gptscript/pkg/credentials" + "github.com/gptscript-ai/gptscript/pkg/engine" "github.com/gptscript-ai/gptscript/pkg/hash" "github.com/gptscript-ai/gptscript/pkg/mvl" "github.com/gptscript-ai/gptscript/pkg/prompt" @@ -132,7 +133,7 @@ func NewClient(ctx context.Context, credStore credentials.CredentialStore, opts }, nil } -func (c *Client) ProxyInfo() (token, urlBase string) { +func (c *Client) ProxyInfo([]string) (token, urlBase string) { if c.invalidAuth { return "", "" } @@ -157,10 +158,15 @@ func (c *Client) Supports(ctx context.Context, modelName string) (bool, error) { return false, InvalidAuthError{} } - return slices.Contains(models, modelName), nil + for _, model := range models { + if model.ID == modelName { + return true, nil + } + } + return false, nil } -func (c *Client) ListModels(ctx context.Context, providers ...string) (result []string, _ error) { +func (c *Client) ListModels(ctx context.Context, providers ...string) ([]openai.Model, error) { // Only serve if providers is empty or "" is in the list if len(providers) != 0 && !slices.Contains(providers, "") { return nil, nil @@ -179,11 +185,10 @@ func (c *Client) ListModels(ctx context.Context, providers ...string) (result [] if err != nil { return nil, err } - for _, model := range models.Models { - result = append(result, model.ID) - } - sort.Strings(result) - return result, nil + sort.Slice(models.Models, func(i, j int) bool { + return models.Models[i].ID < models.Models[j].ID + }) + return models.Models, nil } func (c *Client) cacheKey(request openai.ChatCompletionRequest) any { @@ -212,15 +217,15 @@ func (c *Client) seed(request openai.ChatCompletionRequest) int { return hash.Seed(newRequest) } -func (c *Client) fromCache(ctx context.Context, messageRequest types.CompletionRequest, request openai.ChatCompletionRequest) (result []openai.ChatCompletionStreamResponse, _ bool, _ error) { +func (c *Client) fromCache(ctx context.Context, messageRequest types.CompletionRequest, request openai.ChatCompletionRequest) (result types.CompletionMessage, _ bool, _ error) { if !messageRequest.GetCache() { - return nil, false, nil + return types.CompletionMessage{}, false, nil } found, err := c.cache.Get(ctx, c.cacheKey(request), &result) if err != nil { - return nil, false, err + return types.CompletionMessage{}, false, err } else if !found { - return nil, false, nil + return types.CompletionMessage{}, false, nil } return result, true, nil } @@ -277,10 +282,7 @@ func toMessages(request types.CompletionRequest, compat bool) (result []openai.C chatMessage.ToolCalls = append(chatMessage.ToolCalls, toToolCall(*content.ToolCall)) } if content.Text != "" { - chatMessage.MultiContent = append(chatMessage.MultiContent, openai.ChatMessagePart{ - Type: openai.ChatMessagePartTypeText, - Text: content.Text, - }) + chatMessage.MultiContent = append(chatMessage.MultiContent, textToMultiContent(content.Text)...) } } @@ -302,9 +304,38 @@ func toMessages(request types.CompletionRequest, compat bool) (result []openai.C return } -func (c *Client) Call(ctx context.Context, messageRequest types.CompletionRequest, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { +const imagePrefix = "data:image/png;base64," + +func textToMultiContent(text string) []openai.ChatMessagePart { + var chatParts []openai.ChatMessagePart + parts := strings.Split(text, "\n") + for i := len(parts) - 1; i >= 0; i-- { + if strings.HasPrefix(parts[i], imagePrefix) { + chatParts = append(chatParts, openai.ChatMessagePart{ + Type: openai.ChatMessagePartTypeImageURL, + ImageURL: &openai.ChatMessageImageURL{ + URL: parts[i], + }, + }) + parts = parts[:i] + } else { + break + } + } + if len(parts) > 0 { + chatParts = append(chatParts, openai.ChatMessagePart{ + Type: openai.ChatMessagePartTypeText, + Text: strings.Join(parts, "\n"), + }) + } + + slices.Reverse(chatParts) + return chatParts +} + +func (c *Client) Call(ctx context.Context, messageRequest types.CompletionRequest, env []string, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { if err := c.ValidAuth(); err != nil { - if err := c.RetrieveAPIKey(ctx); err != nil { + if err := c.RetrieveAPIKey(ctx, env); err != nil { return nil, err } } @@ -318,16 +349,29 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques return nil, err } + toolTokenCount, err := countTools(messageRequest.Tools) + if err != nil { + return nil, err + } + if messageRequest.Chat { // Check the last message. If it is from a tool call, and if it takes up more than 80% of the budget on its own, reject it. lastMessage := msgs[len(msgs)-1] - if lastMessage.Role == string(types.CompletionMessageRoleTypeTool) && countMessage(lastMessage) > int(float64(getBudget(messageRequest.MaxTokens))*0.8) { + lastMessageCount, err := countMessage(lastMessage) + if err != nil { + return nil, err + } + + if lastMessage.Role == string(types.CompletionMessageRoleTypeTool) && lastMessageCount+toolTokenCount > int(float64(getBudget(messageRequest.MaxTokens))*0.8) { // We need to update it in the msgs slice for right now and in the messageRequest for future calls. msgs[len(msgs)-1].Content = TooLongMessage messageRequest.Messages[len(messageRequest.Messages)-1].Content = types.Text(TooLongMessage) } - msgs = dropMessagesOverCount(messageRequest.MaxTokens, msgs) + msgs, err = dropMessagesOverCount(messageRequest.MaxTokens, toolTokenCount, msgs) + if err != nil { + return nil, err + } } if len(msgs) == 0 { @@ -356,6 +400,7 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques } } + toolMapping := map[string]string{} for _, tool := range messageRequest.Tools { var params any = tool.Function.Parameters if tool.Function.Parameters == nil || len(tool.Function.Parameters.Properties) == 0 { @@ -365,6 +410,10 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques } } + if tool.Function.ToolID != "" { + toolMapping[tool.Function.Name] = tool.Function.ToolID + } + request.Tools = append(request.Tools, openai.Tool{ Type: openai.ToolTypeFunction, Function: &openai.FunctionDefinition{ @@ -378,7 +427,10 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques id := counter.Next() status <- types.CompletionStatus{ CompletionID: id, - Request: request, + Request: map[string]any{ + "chatCompletion": request, + "toolMapping": toolMapping, + }, } var cacheResponse bool @@ -388,11 +440,11 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques IncludeUsage: true, } } - response, ok, err := c.fromCache(ctx, messageRequest, request) + result, ok, err := c.fromCache(ctx, messageRequest, request) if err != nil { return nil, err } else if !ok { - response, err = c.call(ctx, request, id, status) + result, err = c.call(ctx, request, id, env, status) // If we got back a context length exceeded error, keep retrying and shrinking the message history until we pass. var apiError *openai.APIError @@ -400,9 +452,8 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques // Decrease maxTokens by 10% to make garbage collection more aggressive. // The retry loop will further decrease maxTokens if needed. maxTokens := decreaseTenPercent(messageRequest.MaxTokens) - response, err = c.contextLimitRetryLoop(ctx, request, id, maxTokens, status) + result, err = c.contextLimitRetryLoop(ctx, request, id, env, maxTokens, toolTokenCount, status) } - if err != nil { return nil, err } @@ -410,11 +461,6 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques cacheResponse = true } - result := types.CompletionMessage{} - for _, response := range response { - result = appendMessage(result, response) - } - for i, content := range result.Content { if content.ToolCall != nil && content.ToolCall.ID == "" { content.ToolCall.ID = "call_" + hash.ID(content.ToolCall.Function.Name, content.ToolCall.Function.Arguments)[:8] @@ -432,7 +478,6 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques status <- types.CompletionStatus{ CompletionID: id, - Chunks: response, Response: result, Usage: result.Usage, Cached: cacheResponse, @@ -441,16 +486,20 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques return &result, nil } -func (c *Client) contextLimitRetryLoop(ctx context.Context, request openai.ChatCompletionRequest, id string, maxTokens int, status chan<- types.CompletionStatus) ([]openai.ChatCompletionStreamResponse, error) { +func (c *Client) contextLimitRetryLoop(ctx context.Context, request openai.ChatCompletionRequest, id string, env []string, maxTokens int, toolTokenCount int, status chan<- types.CompletionStatus) (types.CompletionMessage, error) { var ( - response []openai.ChatCompletionStreamResponse + response types.CompletionMessage err error ) for range 10 { // maximum 10 tries // Try to drop older messages again, with a decreased max tokens. - request.Messages = dropMessagesOverCount(maxTokens, request.Messages) - response, err = c.call(ctx, request, id, status) + request.Messages, err = dropMessagesOverCount(maxTokens, toolTokenCount, request.Messages) + if err != nil { + return types.CompletionMessage{}, err + } + + response, err = c.call(ctx, request, id, env, status) if err == nil { return response, nil } @@ -461,10 +510,10 @@ func (c *Client) contextLimitRetryLoop(ctx context.Context, request openai.ChatC maxTokens = decreaseTenPercent(maxTokens) continue } - return nil, err + return types.CompletionMessage{}, err } - return nil, err + return types.CompletionMessage{}, err } func appendMessage(msg types.CompletionMessage, response openai.ChatCompletionStreamResponse) types.CompletionMessage { @@ -540,78 +589,132 @@ func override(left, right string) string { return left } -func (c *Client) call(ctx context.Context, request openai.ChatCompletionRequest, transactionID string, partial chan<- types.CompletionStatus) (responses []openai.ChatCompletionStreamResponse, _ error) { +const WaitingMessage = "Waiting for model response..." + +func (c *Client) call(ctx context.Context, request openai.ChatCompletionRequest, transactionID string, env []string, partial chan<- types.CompletionStatus) (types.CompletionMessage, error) { streamResponse := os.Getenv("GPTSCRIPT_INTERNAL_OPENAI_STREAMING") != "false" partial <- types.CompletionStatus{ CompletionID: transactionID, PartialResponse: &types.CompletionMessage{ Role: types.CompletionMessageRoleTypeAssistant, - Content: types.Text("Waiting for model response..."), + Content: types.Text(WaitingMessage), }, } + var ( + headers map[string]string + modelProviderEnv []string + retryOpts = []openai.RetryOptions{ + { + Retries: 5, + RetryAboveCode: 499, // 5xx errors + RetryCodes: []int{429}, // 429 Too Many Requests (ratelimit) + }, + } + ) + for _, e := range env { + if strings.HasPrefix(e, "GPTSCRIPT_MODEL_PROVIDER_") { + modelProviderEnv = append(modelProviderEnv, e) + } else if strings.HasPrefix(e, "GPTSCRIPT_DISABLE_RETRIES") { + retryOpts = nil + } + } + + if len(modelProviderEnv) > 0 { + headers = map[string]string{ + "X-GPTScript-Env": strings.Join(modelProviderEnv, ","), + } + } + slog.Debug("calling openai", "message", request.Messages) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + engineCtx, ok := engine.FromContext(ctx) + if ok { + engineCtx.OnUserCancel(ctx, cancel) + } + if !streamResponse { request.StreamOptions = nil - resp, err := c.c.CreateChatCompletion(ctx, request) + resp, err := c.c.CreateChatCompletion(ctx, request, headers, retryOpts...) if err != nil { - return nil, err + if errors.Is(err, context.Canceled) { + err = nil + } + return types.CompletionMessage{}, err } - return []openai.ChatCompletionStreamResponse{ - { - ID: resp.ID, - Object: resp.Object, - Created: resp.Created, - Model: resp.Model, - Usage: resp.Usage, - Choices: []openai.ChatCompletionStreamChoice{ - { - Index: resp.Choices[0].Index, - Delta: openai.ChatCompletionStreamChoiceDelta{ - Content: resp.Choices[0].Message.Content, - Role: resp.Choices[0].Message.Role, - FunctionCall: resp.Choices[0].Message.FunctionCall, - ToolCalls: resp.Choices[0].Message.ToolCalls, - }, - FinishReason: resp.Choices[0].FinishReason, + return appendMessage(types.CompletionMessage{}, openai.ChatCompletionStreamResponse{ + ID: resp.ID, + Object: resp.Object, + Created: resp.Created, + Model: resp.Model, + Usage: resp.Usage, + Choices: []openai.ChatCompletionStreamChoice{ + { + Index: resp.Choices[0].Index, + Delta: openai.ChatCompletionStreamChoiceDelta{ + Content: resp.Choices[0].Message.Content, + Role: resp.Choices[0].Message.Role, + FunctionCall: resp.Choices[0].Message.FunctionCall, + ToolCalls: resp.Choices[0].Message.ToolCalls, }, + FinishReason: resp.Choices[0].FinishReason, }, }, - }, nil + }), nil } - - stream, err := c.c.CreateChatCompletionStream(ctx, request) + stream, err := c.c.CreateChatCompletionStream(ctx, request, headers, retryOpts...) if err != nil { - return nil, err + if errors.Is(err, context.Canceled) { + return types.CompletionMessage{ + Content: []types.ContentPart{ + { + Text: "User aborted the chat before model could respond", + }, + }, + Role: types.CompletionMessageRoleTypeAssistant, + }, nil + } + return types.CompletionMessage{}, err } defer stream.Close() - var partialMessage types.CompletionMessage + var ( + partialMessage types.CompletionMessage + start = time.Now() + ) for { response, err := stream.Recv() - if err == io.EOF { - return responses, c.cache.Store(ctx, c.cacheKey(request), responses) + if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) { + if len(partialMessage.Content) > 0 && partialMessage.Content[0].Text == "" && errors.Is(err, context.Canceled) { + // Place a text holder if LLM doesn't respond or user cancel the stream before it can produce any response. + // In anthropic models it will yield an error about non-empty message for assistant message + partialMessage.Content[0].Text = "User aborted the chat or chat finished before LLM can respond" + } + // If the stream is finished, either because we got an EOF or the context was canceled, + // then we're done. The cache won't save the response if the context was canceled. + return partialMessage, c.cache.Store(ctx, c.cacheKey(request), partialMessage) } else if err != nil { - return nil, err - } - if len(response.Choices) > 0 { - slog.Debug("stream", "content", response.Choices[0].Delta.Content) + return types.CompletionMessage{}, err } + partialMessage = appendMessage(partialMessage, response) if partial != nil { - partialMessage = appendMessage(partialMessage, response) - partial <- types.CompletionStatus{ - CompletionID: transactionID, - PartialResponse: &partialMessage, + if time.Since(start) > 100*time.Millisecond { + partial <- types.CompletionStatus{ + CompletionID: transactionID, + PartialResponse: &partialMessage, + } + start = time.Now() } } - responses = append(responses, response) } } -func (c *Client) RetrieveAPIKey(ctx context.Context) error { - k, err := prompt.GetModelProviderCredential(ctx, c.credStore, BuiltinCredName, "OPENAI_API_KEY", "Please provide your OpenAI API key:", gcontext.GetEnv(ctx)) +func (c *Client) RetrieveAPIKey(ctx context.Context, env []string) error { + k, err := prompt.GetModelProviderCredential(ctx, c.credStore, BuiltinCredName, "OPENAI_API_KEY", "Please provide your OpenAI API key:", env) if err != nil { return err } diff --git a/pkg/openai/client_test.go b/pkg/openai/client_test.go index 30f1705b..78f3eac2 100644 --- a/pkg/openai/client_test.go +++ b/pkg/openai/client_test.go @@ -9,6 +9,44 @@ import ( "github.com/hexops/valast" ) +func TestTextToMultiContent(t *testing.T) { + autogold.Expect([]openai.ChatMessagePart{{ + Type: "text", + Text: "hi\ndata:image/png;base64,xxxxx\n", + }}).Equal(t, textToMultiContent("hi\ndata:image/png;base64,xxxxx\n")) + + autogold.Expect([]openai.ChatMessagePart{ + { + Type: "text", + Text: "hi", + }, + { + Type: "image_url", + ImageURL: &openai.ChatMessageImageURL{URL: "data:image/png;base64,xxxxx"}, + }, + }).Equal(t, textToMultiContent("hi\ndata:image/png;base64,xxxxx")) + + autogold.Expect([]openai.ChatMessagePart{{ + Type: "image_url", + ImageURL: &openai.ChatMessageImageURL{URL: "data:image/png;base64,xxxxx"}, + }}).Equal(t, textToMultiContent("data:image/png;base64,xxxxx")) + + autogold.Expect([]openai.ChatMessagePart{ + { + Type: "text", + Text: "\none\ntwo", + }, + { + Type: "image_url", + ImageURL: &openai.ChatMessageImageURL{URL: "data:image/png;base64,xxxxx"}, + }, + { + Type: "image_url", + ImageURL: &openai.ChatMessageImageURL{URL: "data:image/png;base64,yyyyy"}, + }, + }).Equal(t, textToMultiContent("\none\ntwo\ndata:image/png;base64,xxxxx\ndata:image/png;base64,yyyyy")) +} + func Test_appendMessage(t *testing.T) { autogold.Expect(types.CompletionMessage{Content: []types.ContentPart{ {ToolCall: &types.CompletionToolCall{ diff --git a/pkg/openai/count.go b/pkg/openai/count.go index ffd902e5..3c3de1a9 100644 --- a/pkg/openai/count.go +++ b/pkg/openai/count.go @@ -1,10 +1,19 @@ package openai import ( + "encoding/json" + openai "github.com/gptscript-ai/chat-completion-client" + "github.com/gptscript-ai/gptscript/pkg/types" + "github.com/pkoukk/tiktoken-go" + tiktoken_loader "github.com/pkoukk/tiktoken-go-loader" ) -const DefaultMaxTokens = 128_000 +func init() { + tiktoken.SetBpeLoader(tiktoken_loader.NewOfflineLoader()) +} + +const DefaultMaxTokens = 400_000 // This is the limit for GPT-5 func decreaseTenPercent(maxTokens int) int { maxTokens = getBudget(maxTokens) @@ -12,22 +21,26 @@ func decreaseTenPercent(maxTokens int) int { } func getBudget(maxTokens int) int { - if maxTokens == 0 { + if maxTokens <= 0 { return DefaultMaxTokens } return maxTokens } -func dropMessagesOverCount(maxTokens int, msgs []openai.ChatCompletionMessage) (result []openai.ChatCompletionMessage) { +func dropMessagesOverCount(maxTokens, toolTokenCount int, msgs []openai.ChatCompletionMessage) (result []openai.ChatCompletionMessage, err error) { var ( lastSystem int withinBudget int - budget = getBudget(maxTokens) + budget = getBudget(maxTokens) - toolTokenCount ) for i, msg := range msgs { if msg.Role == openai.ChatMessageRoleSystem { - budget -= countMessage(msg) + count, err := countMessage(msg) + if err != nil { + return nil, err + } + budget -= count lastSystem = i result = append(result, msg) } else { @@ -37,7 +50,11 @@ func dropMessagesOverCount(maxTokens int, msgs []openai.ChatCompletionMessage) ( for i := len(msgs) - 1; i > lastSystem; i-- { withinBudget = i - budget -= countMessage(msgs[i]) + count, err := countMessage(msgs[i]) + if err != nil { + return nil, err + } + budget -= count if budget <= 0 { break } @@ -54,22 +71,42 @@ func dropMessagesOverCount(maxTokens int, msgs []openai.ChatCompletionMessage) ( if withinBudget == len(msgs)-1 { // We are going to drop all non system messages, which seems useless, so just return them // all and let it fail - return msgs + return msgs, nil } - return append(result, msgs[withinBudget:]...) + return append(result, msgs[withinBudget:]...), nil } -func countMessage(msg openai.ChatCompletionMessage) (count int) { - count += len(msg.Role) - count += len(msg.Content) +func countMessage(msg openai.ChatCompletionMessage) (int, error) { + encoding, err := tiktoken.GetEncoding("o200k_base") + if err != nil { + return 0, err + } + + count := len(encoding.Encode(msg.Role, nil, nil)) + count += len(encoding.Encode(msg.Content, nil, nil)) for _, content := range msg.MultiContent { - count += len(content.Text) + count += len(encoding.Encode(content.Text, nil, nil)) } for _, tool := range msg.ToolCalls { - count += len(tool.Function.Name) - count += len(tool.Function.Arguments) + count += len(encoding.Encode(tool.Function.Name, nil, nil)) + count += len(encoding.Encode(tool.Function.Arguments, nil, nil)) } - count += len(msg.ToolCallID) - return count / 3 + count += len(encoding.Encode(msg.ToolCallID, nil, nil)) + + return count, nil +} + +func countTools(tools []types.ChatCompletionTool) (int, error) { + encoding, err := tiktoken.GetEncoding("o200k_base") + if err != nil { + return 0, err + } + + toolJSON, err := json.Marshal(tools) + if err != nil { + return 0, err + } + + return len(encoding.Encode(string(toolJSON), nil, nil)), nil } diff --git a/pkg/openapi/run.go b/pkg/openapi/run.go index ac1ec660..237d8b57 100644 --- a/pkg/openapi/run.go +++ b/pkg/openapi/run.go @@ -8,7 +8,6 @@ import ( "mime/multipart" "net/http" "net/url" - "os" "strings" "github.com/getkin/kin-openapi/openapi3" @@ -69,22 +68,18 @@ func Run(operationID, defaultHost, args string, t *openapi3.T, envs []string) (s return "", false, fmt.Errorf("failed to create request: %w", err) } - // Check for authentication (only if using HTTPS or localhost) - if u.Scheme == "https" || u.Hostname() == "localhost" || u.Hostname() == "127.0.0.1" { - if len(opInfo.SecurityInfos) > 0 { - if err := HandleAuths(req, envMap, opInfo.SecurityInfos); err != nil { - return "", false, fmt.Errorf("error setting up authentication: %w", err) - } + // Check for authentication + if len(opInfo.SecurityInfos) > 0 { + if err := HandleAuths(req, envMap, opInfo.SecurityInfos); err != nil { + return "", false, fmt.Errorf("error setting up authentication: %w", err) } + } - // If there is a bearer token set for the whole server, and no Authorization header has been defined, use it. - if token, ok := envMap["GPTSCRIPT_"+env.ToEnvLike(u.Hostname())+"_BEARER_TOKEN"]; ok { - if req.Header.Get("Authorization") == "" { - req.Header.Set("Authorization", "Bearer "+token) - } + // If there is a bearer token set for the whole server, and no Authorization header has been defined, use it. + if token, ok := envMap["GPTSCRIPT_"+env.ToEnvLike(u.Hostname())+"_BEARER_TOKEN"]; ok { + if req.Header.Get("Authorization") == "" { + req.Header.Set("Authorization", "Bearer "+token) } - } else { - fmt.Fprintf(os.Stderr, "no auth") } // Handle query parameters diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 956822dd..3d26d9cc 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -1,7 +1,6 @@ package parser import ( - "bufio" "fmt" "io" "maps" @@ -11,14 +10,16 @@ import ( "strconv" "strings" - "github.com/getkin/kin-openapi/openapi3" "github.com/gptscript-ai/gptscript/pkg/types" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) var ( sepRegex = regexp.MustCompile(`^\s*---+\s*$`) + endHeaderRegex = regexp.MustCompile(`^\s*===+\s*$`) strictSepRegex = regexp.MustCompile(`^---\n$`) - skipRegex = regexp.MustCompile(`^![-.:*\w]+\s*$`) + skipRegex = regexp.MustCompile(`^![ -.:*\w]+\s*$`) + nameRegex = regexp.MustCompile(`^[a-z]+$`) ) func normalize(key string) string { @@ -52,10 +53,10 @@ func csv(line string) (result []string) { } func addArg(line string, tool *types.Tool) error { - if tool.Parameters.Arguments == nil { - tool.Parameters.Arguments = &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{}, + if tool.Arguments == nil { + tool.Arguments = &jsonschema.Schema{ + Type: "object", + Properties: make(map[string]*jsonschema.Schema, 1), } } @@ -64,17 +65,15 @@ func addArg(line string, tool *types.Tool) error { return fmt.Errorf("invalid arg format: %s", line) } - tool.Parameters.Arguments.Properties[key] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: strings.TrimSpace(value), - Type: &openapi3.Types{"string"}, - }, + tool.Arguments.Properties[key] = &jsonschema.Schema{ + Description: strings.TrimSpace(value), + Type: "string", } return nil } -func isParam(line string, tool *types.Tool) (_ bool, err error) { +func isParam(line string, tool *types.Tool, scan *simplescanner) (_ bool, err error) { key, value, ok := strings.Cut(line, ":") if !ok { return false, nil @@ -82,53 +81,65 @@ func isParam(line string, tool *types.Tool) (_ bool, err error) { value = strings.TrimSpace(value) switch normalize(key) { case "name": - tool.Parameters.Name = value + tool.Name = value case "modelprovider": - tool.Parameters.ModelProvider = true + tool.ModelProvider = true case "model", "modelname": - tool.Parameters.ModelName = value + tool.ModelName = value case "globalmodel", "globalmodelname": - tool.Parameters.GlobalModelName = value + tool.GlobalModelName = value case "description": - tool.Parameters.Description = value + tool.Description = scan.AddMultiline(value) case "internalprompt": v, err := toBool(value) if err != nil { return false, err } - tool.Parameters.InternalPrompt = &v + tool.InternalPrompt = &v case "chat": v, err := toBool(value) if err != nil { return false, err } - tool.Parameters.Chat = v + tool.Chat = v case "export", "exporttool", "exports", "exporttools", "sharetool", "sharetools", "sharedtool", "sharedtools": - tool.Parameters.Export = append(tool.Parameters.Export, csv(value)...) + tool.Export = append(tool.Export, csv(scan.AddMultiline(value))...) case "tool", "tools": - tool.Parameters.Tools = append(tool.Parameters.Tools, csv(value)...) + tool.Tools = append(tool.Tools, csv(scan.AddMultiline(value))...) case "inputfilter", "inputfilters": - tool.Parameters.InputFilters = append(tool.Parameters.InputFilters, csv(value)...) + tool.InputFilters = append(tool.InputFilters, csv(scan.AddMultiline(value))...) case "shareinputfilter", "shareinputfilters", "sharedinputfilter", "sharedinputfilters": - tool.Parameters.ExportInputFilters = append(tool.Parameters.ExportInputFilters, csv(value)...) + tool.ExportInputFilters = append(tool.ExportInputFilters, csv(scan.AddMultiline(value))...) case "outputfilter", "outputfilters": - tool.Parameters.OutputFilters = append(tool.Parameters.OutputFilters, csv(value)...) + tool.OutputFilters = append(tool.OutputFilters, csv(scan.AddMultiline(value))...) case "shareoutputfilter", "shareoutputfilters", "sharedoutputfilter", "sharedoutputfilters": - tool.Parameters.ExportOutputFilters = append(tool.Parameters.ExportOutputFilters, csv(value)...) + tool.ExportOutputFilters = append(tool.ExportOutputFilters, csv(scan.AddMultiline(value))...) case "agent", "agents": - tool.Parameters.Agents = append(tool.Parameters.Agents, csv(value)...) + tool.Agents = append(tool.Agents, csv(scan.AddMultiline(value))...) case "globaltool", "globaltools": - tool.Parameters.GlobalTools = append(tool.Parameters.GlobalTools, csv(value)...) + tool.GlobalTools = append(tool.GlobalTools, csv(scan.AddMultiline(value))...) case "exportcontext", "exportcontexts", "sharecontext", "sharecontexts", "sharedcontext", "sharedcontexts": - tool.Parameters.ExportContext = append(tool.Parameters.ExportContext, csv(value)...) + tool.ExportContext = append(tool.ExportContext, csv(scan.AddMultiline(value))...) case "context": - tool.Parameters.Context = append(tool.Parameters.Context, csv(value)...) + tool.Context = append(tool.Context, csv(scan.AddMultiline(value))...) + case "stdin": + b, err := toBool(value) + if err != nil { + return false, err + } + tool.Stdin = b + case "metadata": + mkey, mvalue, _ := strings.Cut(scan.AddMultiline(value), ":") + if tool.MetaData == nil { + tool.MetaData = map[string]string{} + } + tool.MetaData[strings.TrimSpace(mkey)] = strings.TrimSpace(mvalue) case "args", "arg", "param", "params", "parameters", "parameter": - if err := addArg(value, tool); err != nil { + if err := addArg(scan.AddMultiline(value), tool); err != nil { return false, err } case "maxtoken", "maxtokens": - tool.Parameters.MaxTokens, err = strconv.Atoi(value) + tool.MaxTokens, err = strconv.Atoi(value) if err != nil { return false, err } @@ -137,25 +148,25 @@ func isParam(line string, tool *types.Tool) (_ bool, err error) { if err != nil { return false, err } - tool.Parameters.Cache = &b + tool.Cache = &b case "jsonmode", "json", "jsonoutput", "jsonformat", "jsonresponse": - tool.Parameters.JSONResponse, err = toBool(value) + tool.JSONResponse, err = toBool(value) if err != nil { return false, err } case "temperature": - tool.Parameters.Temperature, err = toFloatPtr(value) + tool.Temperature, err = toFloatPtr(value) if err != nil { return false, err } case "credentials", "creds", "credential", "cred": - tool.Parameters.Credentials = append(tool.Parameters.Credentials, value) + tool.Credentials = append(tool.Credentials, csv(scan.AddMultiline(value))...) case "sharecredentials", "sharecreds", "sharecredential", "sharecred", "sharedcredentials", "sharedcreds", "sharedcredential", "sharedcred": - tool.Parameters.ExportCredentials = append(tool.Parameters.ExportCredentials, value) + tool.ExportCredentials = append(tool.ExportCredentials, scan.AddMultiline(value)) case "type": tool.Type = types.ToolType(strings.ToLower(value)) default: - return false, nil + return nameRegex.MatchString(key), nil } return true, nil @@ -198,7 +209,7 @@ type context struct { func (c *context) finish(tools *[]Node) { c.tool.Instructions = strings.TrimSpace(strings.Join(c.instructions, "")) if c.tool.Instructions != "" || - c.tool.Parameters.Name != "" || + c.tool.Name != "" || len(c.tool.Export) > 0 || len(c.tool.Tools) > 0 || c.tool.GlobalModelName != "" || @@ -206,6 +217,7 @@ func (c *context) finish(tools *[]Node) { len(c.tool.ExportInputFilters) > 0 || len(c.tool.ExportOutputFilters) > 0 || len(c.tool.Agents) > 0 || + len(c.tool.ExportCredentials) > 0 || c.tool.Chat { *tools = append(*tools, Node{ ToolNode: &ToolNode{ @@ -249,7 +261,7 @@ func writeSep(buf *strings.Builder, lastText bool) { } } -func (d Document) String() string { +func (d Document) Print() string { buf := strings.Builder{} lastText := false for _, node := range d.Nodes { @@ -260,7 +272,7 @@ func (d Document) String() string { } if node.ToolNode != nil { writeSep(&buf, lastText) - buf.WriteString(node.ToolNode.Tool.String()) + buf.WriteString(node.ToolNode.Tool.Print()) lastText = false } } @@ -391,7 +403,10 @@ func assignMetadata(nodes []Node) (result []Node) { for _, node := range nodes { if node.ToolNode != nil { - node.ToolNode.Tool.MetaData = metadata[node.ToolNode.Tool.Name] + if node.ToolNode.Tool.MetaData == nil { + node.ToolNode.Tool.MetaData = map[string]string{} + } + maps.Copy(node.ToolNode.Tool.MetaData, metadata[node.ToolNode.Tool.Name]) for wildcard := range metadata { if strings.Contains(wildcard, "*") { if m, err := path.Match(wildcard, node.ToolNode.Tool.Name); m && err == nil { @@ -433,15 +448,71 @@ func isGPTScriptHashBang(line string) bool { return false } -func parse(input io.Reader) ([]Node, error) { - scan := bufio.NewScanner(input) +type simplescanner struct { + lines []string +} +func newSimpleScanner(data []byte) *simplescanner { + if len(data) == 0 { + return &simplescanner{} + } + lines := strings.Split(string(data), "\n") + return &simplescanner{ + lines: append([]string{""}, lines...), + } +} + +func dropCR(s string) string { + if len(s) > 0 && s[len(s)-1] == '\r' { + return s[:len(s)-1] + } + return s +} + +func (s *simplescanner) AddMultiline(current string) string { + result := current + for { + if len(s.lines) < 2 || len(s.lines[1]) == 0 { + return result + } + if strings.HasPrefix(s.lines[1], " ") || strings.HasPrefix(s.lines[1], "\t") { + result += " " + dropCR(s.lines[1]) + s.lines = s.lines[1:] + } else { + return result + } + } +} + +func (s *simplescanner) Text() string { + if len(s.lines) == 0 { + return "" + } + return dropCR(s.lines[0]) +} + +func (s *simplescanner) Scan() bool { + if len(s.lines) == 0 { + return false + } + s.lines = s.lines[1:] + return true +} + +func parse(input io.Reader) ([]Node, error) { var ( tools []Node context context lineNo int ) + data, err := io.ReadAll(input) + if err != nil { + return nil, err + } + + scan := newSimpleScanner(data) + for scan.Scan() { lineNo++ if context.tool.Source.LineNo == 0 { @@ -488,11 +559,15 @@ func parse(input io.Reader) ([]Node, error) { } // Look for params - if isParam, err := isParam(line, &context.tool); err != nil { + if isParam, err := isParam(line, &context.tool, scan); err != nil { return nil, NewErrLine("", lineNo, err) } else if isParam { context.seenParam = true continue + } else if endHeaderRegex.MatchString(line) { + // force the end of the header and don't include the current line in the header + context.inBody = true + continue } } diff --git a/pkg/parser/parser_test.go b/pkg/parser/parser_test.go index f98b74e2..a3263539 100644 --- a/pkg/parser/parser_test.go +++ b/pkg/parser/parser_test.go @@ -1,6 +1,7 @@ package parser import ( + "reflect" "strings" "testing" @@ -241,9 +242,27 @@ share output filters: shared }}).Equal(t, out) } +func TestParseMetaDataSpace(t *testing.T) { + input := ` +name: a space +body +--- +!metadata:a space:other +foo bar +` + tools, err := ParseTools(strings.NewReader(input)) + require.NoError(t, err) + + assert.Len(t, tools, 1) + autogold.Expect(map[string]string{ + "other": "foo bar", + }).Equal(t, tools[0].MetaData) +} + func TestParseMetaData(t *testing.T) { input := ` name: first +metadata: foo: bar body --- @@ -269,8 +288,89 @@ foo bar assert.Len(t, tools, 1) autogold.Expect(map[string]string{ + "foo": "bar", "package.json": "foo=base\nf", "requirements.txt": "asdf", "other": "foo bar", }).Equal(t, tools[0].MetaData) + + autogold.Expect(`Name: first +Meta Data: foo: bar +Meta Data: other: foo bar +Meta Data: requirements.txt: asdf + +body +--- +!metadata:first:package.json +foo=base +f +`).Equal(t, tools[0].Print()) +} + +func TestFormatWithBadInstruction(t *testing.T) { + input := types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: "foo", + }, + Instructions: "foo: bar", + }, + } + autogold.Expect("Name: foo\n===\nfoo: bar\n").Equal(t, input.Print()) + + tools, err := ParseTools(strings.NewReader(input.Print())) + require.NoError(t, err) + if reflect.DeepEqual(input, tools[0]) { + t.Errorf("expected %v, got %v", input, tools[0]) + } +} + +func TestSingleTool(t *testing.T) { + input := ` +name: foo + +#!sys.echo +hi +` + + tools, err := ParseTools(strings.NewReader(input)) + require.NoError(t, err) + autogold.Expect(types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{Name: "foo"}, + Instructions: "#!sys.echo\nhi", + }, + Source: types.ToolSource{LineNo: 1}, + }).Equal(t, tools[0]) +} + +func TestMultiline(t *testing.T) { + input := ` +name: first +credential: foo + , bar, + baz +model: the model + +body +` + tools, err := ParseTools(strings.NewReader(input)) + require.NoError(t, err) + + assert.Len(t, tools, 1) + autogold.Expect(types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: "first", + ModelName: "the model", + Credentials: []string{ + "foo", + "bar", + "baz", + }, + }, + Instructions: "body", + }, + Source: types.ToolSource{LineNo: 1}, + }).Equal(t, tools[0]) } diff --git a/pkg/prompt/prompt.go b/pkg/prompt/prompt.go index f91a04b6..fa4beeb6 100644 --- a/pkg/prompt/prompt.go +++ b/pkg/prompt/prompt.go @@ -52,7 +52,7 @@ func sysPromptHTTP(ctx context.Context, envs []string, url string, prompt types. func SysPrompt(ctx context.Context, envs []string, input string, _ chan<- string) (_ string, err error) { var params struct { Message string `json:"message,omitempty"` - Fields string `json:"fields,omitempty"` + Fields types.Fields `json:"fields,omitempty"` Sensitive string `json:"sensitive,omitempty"` Metadata map[string]string `json:"metadata,omitempty"` } @@ -60,16 +60,11 @@ func SysPrompt(ctx context.Context, envs []string, input string, _ chan<- string return "", err } - var fields []string for _, env := range envs { if url, ok := strings.CutPrefix(env, types.PromptURLEnvVar+"="); ok { - if params.Fields != "" { - fields = strings.Split(params.Fields, ",") - } - httpPrompt := types.Prompt{ Message: params.Message, - Fields: fields, + Fields: params.Fields, Sensitive: params.Sensitive == "true", Metadata: params.Metadata, } @@ -102,21 +97,25 @@ func sysPrompt(ctx context.Context, req types.Prompt) (_ string, err error) { results := map[string]string{} for _, f := range req.Fields { var ( - value string - msg = f + value string + msg = f.Name + sensitive = req.Sensitive ) + if f.Sensitive != nil { + sensitive = *f.Sensitive + } if len(req.Fields) == 1 && req.Message != "" { msg = req.Message } - if req.Sensitive { - err = survey.AskOne(&survey.Password{Message: msg}, &value, survey.WithStdio(os.Stdin, os.Stderr, os.Stderr)) + if sensitive { + err = survey.AskOne(&survey.Password{Message: msg, Help: f.Description}, &value, survey.WithStdio(os.Stdin, os.Stderr, os.Stderr)) } else { - err = survey.AskOne(&survey.Input{Message: msg}, &value, survey.WithStdio(os.Stdin, os.Stderr, os.Stderr)) + err = survey.AskOne(&survey.Input{Message: msg, Help: f.Description}, &value, survey.WithStdio(os.Stdin, os.Stderr, os.Stderr)) } if err != nil { return "", err } - results[f] = value + results[f.Name] = value } resultsStr, err := json.Marshal(results) diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index fa1d40c2..441a01dd 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -9,8 +9,8 @@ import ( "strings" "sync" + openai2 "github.com/gptscript-ai/chat-completion-client" "github.com/gptscript-ai/gptscript/pkg/cache" - gcontext "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/engine" env2 "github.com/gptscript-ai/gptscript/pkg/env" @@ -42,13 +42,13 @@ func New(r *runner.Runner, envs []string, cache *cache.Client, credStore credent } } -func (c *Client) Call(ctx context.Context, messageRequest types.CompletionRequest, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { +func (c *Client) Call(ctx context.Context, messageRequest types.CompletionRequest, env []string, status chan<- types.CompletionStatus) (*types.CompletionMessage, error) { _, provider := c.parseModel(messageRequest.Model) if provider == "" { return nil, fmt.Errorf("failed to find remote model %s", messageRequest.Model) } - client, err := c.load(ctx, provider) + client, err := c.load(ctx, provider, env...) if err != nil { return nil, err } @@ -60,10 +60,10 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques modelName = toolName } messageRequest.Model = modelName - return client.Call(ctx, messageRequest, status) + return client.Call(ctx, messageRequest, env, status) } -func (c *Client) ListModels(ctx context.Context, providers ...string) (result []string, _ error) { +func (c *Client) ListModels(ctx context.Context, providers ...string) (result []openai2.Model, _ error) { for _, provider := range providers { client, err := c.load(ctx, provider) if err != nil { @@ -73,12 +73,16 @@ func (c *Client) ListModels(ctx context.Context, providers ...string) (result [] if err != nil { return nil, err } - for _, model := range models { - result = append(result, model+" from "+provider) + for i := range models { + models[i].ID = fmt.Sprintf("%s from %s", models[i].ID, provider) } + + result = append(result, models...) } - sort.Strings(result) + sort.Slice(result, func(i, j int) bool { + return result[i].ID < result[j].ID + }) return } @@ -111,7 +115,7 @@ func isHTTPURL(toolName string) bool { strings.HasPrefix(toolName, "https://") } -func (c *Client) clientFromURL(ctx context.Context, apiURL string) (*openai.Client, error) { +func (c *Client) clientFromURL(ctx context.Context, apiURL string, envs []string) (*openai.Client, error) { parsed, err := url.Parse(apiURL) if err != nil { return nil, err @@ -121,7 +125,7 @@ func (c *Client) clientFromURL(ctx context.Context, apiURL string) (*openai.Clie if key == "" && !isLocalhost(apiURL) { var err error - key, err = c.retrieveAPIKey(ctx, env, apiURL) + key, err = c.retrieveAPIKey(ctx, env, apiURL, envs) if err != nil { return nil, err } @@ -134,7 +138,7 @@ func (c *Client) clientFromURL(ctx context.Context, apiURL string) (*openai.Clie }) } -func (c *Client) load(ctx context.Context, toolName string) (*openai.Client, error) { +func (c *Client) load(ctx context.Context, toolName string, env ...string) (*openai.Client, error) { c.clientsLock.Lock() defer c.clientsLock.Unlock() @@ -144,7 +148,7 @@ func (c *Client) load(ctx context.Context, toolName string) (*openai.Client, err } if isHTTPURL(toolName) { - remoteClient, err := c.clientFromURL(ctx, toolName) + remoteClient, err := c.clientFromURL(ctx, toolName, env) if err != nil { return nil, err } @@ -162,7 +166,7 @@ func (c *Client) load(ctx context.Context, toolName string) (*openai.Client, err return nil, err } - url, err := c.runner.Run(engine.WithToolCategory(ctx, engine.ProviderToolCategory), prg.SetBlocking(), c.envs, "") + url, err := c.runner.Run(engine.WithToolCategory(ctx, engine.ProviderToolCategory), prg.SetBlocking(), c.envs, "", runner.RunOptions{}) if err != nil { return nil, err } @@ -183,8 +187,8 @@ func (c *Client) load(ctx context.Context, toolName string) (*openai.Client, err return oClient, nil } -func (c *Client) retrieveAPIKey(ctx context.Context, env, url string) (string, error) { - return prompt.GetModelProviderCredential(ctx, c.credStore, url, env, fmt.Sprintf("Please provide your API key for %s", url), append(gcontext.GetEnv(ctx), c.envs...)) +func (c *Client) retrieveAPIKey(ctx context.Context, env, url string, envs []string) (string, error) { + return prompt.GetModelProviderCredential(ctx, c.credStore, url, env, fmt.Sprintf("Please provide your API key for %s", url), append(envs, c.envs...)) } func isLocalhost(url string) bool { diff --git a/pkg/repos/download/extract.go b/pkg/repos/download/extract.go index 4cf09f0c..9615d372 100644 --- a/pkg/repos/download/extract.go +++ b/pkg/repos/download/extract.go @@ -14,7 +14,7 @@ import ( "strings" "time" - "github.com/mholt/archiver/v4" + "github.com/mholt/archives" ) func Extract(ctx context.Context, downloadURL, digest, targetDir string) error { @@ -74,17 +74,17 @@ func Extract(ctx context.Context, downloadURL, digest, targetDir string) error { return err } - format, input, err := archiver.Identify(filepath.Base(parsedURL.Path), tmpFile) + format, input, err := archives.Identify(ctx, filepath.Base(parsedURL.Path), tmpFile) if err != nil { return err } - ex, ok := format.(archiver.Extractor) + ex, ok := format.(archives.Extractor) if !ok { return fmt.Errorf("failed to detect proper archive for extraction from %s got: %v", downloadURL, ex) } - err = ex.Extract(ctx, input, nil, func(_ context.Context, f archiver.File) error { + err = ex.Extract(ctx, input, func(_ context.Context, f archives.FileInfo) error { target := filepath.Join(targetDir, f.NameInArchive) if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { return err diff --git a/pkg/repos/get.go b/pkg/repos/get.go index a36c2fe0..d77fb526 100644 --- a/pkg/repos/get.go +++ b/pkg/repos/get.go @@ -4,21 +4,15 @@ import ( "context" "encoding/json" "errors" - "fmt" "io/fs" "os" "path/filepath" - "runtime" + "regexp" "strings" - "sync" - "time" "github.com/BurntSushi/locker" - "github.com/gptscript-ai/gptscript/pkg/config" - "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/hash" "github.com/gptscript-ai/gptscript/pkg/repos/git" - "github.com/gptscript-ai/gptscript/pkg/repos/runtimes/golang" "github.com/gptscript-ai/gptscript/pkg/types" ) @@ -54,154 +48,34 @@ func (n noopRuntime) Setup(_ context.Context, _ types.Tool, _, _ string, _ []str } type Manager struct { - cacheDir string - storageDir string - gitDir string - runtimeDir string - runtimes []Runtime - credHelperConfig *credHelperConfig + cacheDir string + storageDir string + gitDir string + runtimeDir string + systemDirs []string + runtimes []Runtime } -type credHelperConfig struct { - lock sync.Mutex - initialized bool - cliCfg *config.CLIConfig -} +func New(cacheDir, systemDir string, runtimes ...Runtime) *Manager { + var ( + systemDirs []string + root = filepath.Join(cacheDir, "repos") + ) + + if strings.TrimSpace(systemDir) != "" { + systemDirs = regexp.MustCompile("[;:,]").Split(strings.TrimSpace(systemDir), -1) + } -func New(cacheDir string, runtimes ...Runtime) *Manager { - root := filepath.Join(cacheDir, "repos") return &Manager{ cacheDir: cacheDir, storageDir: root, gitDir: filepath.Join(root, "git"), runtimeDir: filepath.Join(root, "runtimes"), + systemDirs: systemDirs, runtimes: runtimes, } } -func (m *Manager) EnsureCredentialHelpers(ctx context.Context) error { - if m.credHelperConfig == nil { - return nil - } - m.credHelperConfig.lock.Lock() - defer m.credHelperConfig.lock.Unlock() - - if !m.credHelperConfig.initialized { - if err := m.deferredSetUpCredentialHelpers(ctx, m.credHelperConfig.cliCfg); err != nil { - return err - } - m.credHelperConfig.initialized = true - } - - return nil -} - -func (m *Manager) SetUpCredentialHelpers(_ context.Context, cliCfg *config.CLIConfig) error { - m.credHelperConfig = &credHelperConfig{ - cliCfg: cliCfg, - } - return nil -} - -func (m *Manager) deferredSetUpCredentialHelpers(ctx context.Context, cliCfg *config.CLIConfig) error { - var ( - helperName = cliCfg.CredentialsStore - distInfo, suffix string - ) - // The file helper is built-in and does not need to be downloaded. - if helperName == config.FileCredHelper { - return nil - } - switch helperName { - case config.WincredCredHelper: - suffix = ".exe" - default: - distInfo = fmt.Sprintf("-%s-%s", runtime.GOOS, runtime.GOARCH) - } - - repoName := credentials.RepoNameForCredentialStore(helperName) - - locker.Lock(repoName) - defer locker.Unlock(repoName) - - credHelperDirs := credentials.GetCredentialHelperDirs(m.cacheDir, helperName) - - // Load the last-checked file to make sure we haven't checked the repo in the last 24 hours. - now := time.Now() - lastChecked, err := os.ReadFile(credHelperDirs.LastCheckedFile) - if err == nil { - if t, err := time.Parse(time.RFC3339, strings.TrimSpace(string(lastChecked))); err == nil && now.Sub(t) < 24*time.Hour { - // Make sure the binary still exists, and if it does, return. - if _, err := os.Stat(filepath.Join(credHelperDirs.BinDir, "gptscript-credential-"+helperName+suffix)); err == nil { - log.Debugf("Credential helper %s up-to-date as of %v, checking for updates after %v", helperName, t, t.Add(24*time.Hour)) - return nil - } - } - } - - if err := os.MkdirAll(filepath.Dir(credHelperDirs.LastCheckedFile), 0755); err != nil { - return err - } - - // Update the last-checked file. - if err := os.WriteFile(credHelperDirs.LastCheckedFile, []byte(now.Format(time.RFC3339)), 0644); err != nil { - return err - } - - gitURL, err := credentials.GitURLForRepoName(repoName) - if err != nil { - return err - } - - tool := types.Tool{ - ToolDef: types.ToolDef{ - Parameters: types.Parameters{ - Name: repoName, - }, - }, - Source: types.ToolSource{ - Repo: &types.Repo{ - Root: gitURL, - }, - }, - } - tag, err := golang.GetLatestTag(tool) - if err != nil { - return err - } - - var needsDownloaded bool - // Check the last revision shasum and see if it is different from the current one. - lastRevision, err := os.ReadFile(credHelperDirs.RevisionFile) - if (err == nil && strings.TrimSpace(string(lastRevision)) != tool.Source.Repo.Root+tag) || errors.Is(err, fs.ErrNotExist) { - // Need to pull the latest version. - needsDownloaded = true - // Update the revision file to the new revision. - if err = os.WriteFile(credHelperDirs.RevisionFile, []byte(tool.Source.Repo.Root+tag), 0644); err != nil { - return err - } - } else if err != nil { - return err - } - - if !needsDownloaded { - // Check for the existence of the credential helper binary. - // If it's there, we have no need to download it and can just return. - if _, err = os.Stat(filepath.Join(credHelperDirs.BinDir, "gptscript-credential-"+helperName+suffix)); err == nil { - return nil - } - } - - // Find the Go runtime and use it to build the credential helper. - for _, rt := range m.runtimes { - if strings.HasPrefix(rt.ID(), "go") { - return rt.(*golang.Runtime).DownloadCredentialHelper(ctx, tool, helperName, distInfo, suffix, credHelperDirs.BinDir) - } - } - - return fmt.Errorf("no Go runtime found to build the credential helper") -} - func (m *Manager) setup(ctx context.Context, runtime Runtime, tool types.Tool, env []string) (string, []string, error) { locker.Lock(tool.ID) defer locker.Unlock(tool.ID) @@ -271,6 +145,12 @@ func (m *Manager) setup(ctx context.Context, runtime Runtime, tool types.Tool, e } func (m *Manager) GetContext(ctx context.Context, tool types.Tool, cmd, env []string) (string, []string, error) { + for _, systemDir := range m.systemDirs { + if strings.HasPrefix(tool.WorkingDir, systemDir) { + return tool.WorkingDir, env, nil + } + } + var isLocal bool if tool.Source.Repo == nil { isLocal = true diff --git a/pkg/repos/get_test.go b/pkg/repos/get_test.go index d59e5513..3a656dc0 100644 --- a/pkg/repos/get_test.go +++ b/pkg/repos/get_test.go @@ -19,7 +19,7 @@ var ( ) func TestManager_GetContext(t *testing.T) { - m := New(testCacheHome, &python.Runtime{ + m := New(testCacheHome, "", &python.Runtime{ Version: "3.11", }) cwd, env, err := m.GetContext(context.Background(), types.Tool{ diff --git a/pkg/repos/runtimes/busybox/busybox.go b/pkg/repos/runtimes/busybox/busybox.go index e4604b06..5c77ee2b 100644 --- a/pkg/repos/runtimes/busybox/busybox.go +++ b/pkg/repos/runtimes/busybox/busybox.go @@ -14,6 +14,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" runtimeEnv "github.com/gptscript-ai/gptscript/pkg/env" "github.com/gptscript-ai/gptscript/pkg/hash" @@ -27,6 +28,7 @@ var releasesData []byte const downloadURL = "https://github.com/gptscript-ai/busybox-w32/releases/download/%s" type Runtime struct { + runtimeSetupLock sync.Mutex } func (r *Runtime) ID() string { @@ -75,6 +77,9 @@ func (r *Runtime) getReleaseAndDigest() (string, string, error) { } func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) { + r.runtimeSetupLock.Lock() + defer r.runtimeSetupLock.Unlock() + url, sha, err := r.getReleaseAndDigest() if err != nil { return "", err diff --git a/pkg/repos/runtimes/default.go b/pkg/repos/runtimes/default.go index a93fb735..ea237cc4 100644 --- a/pkg/repos/runtimes/default.go +++ b/pkg/repos/runtimes/default.go @@ -30,6 +30,6 @@ var Runtimes = []repos.Runtime{ }, } -func Default(cacheDir string) engine.RuntimeManager { - return repos.New(cacheDir, Runtimes...) +func Default(cacheDir, systemDir string) engine.RuntimeManager { + return repos.New(cacheDir, systemDir, Runtimes...) } diff --git a/pkg/repos/runtimes/golang/golang.go b/pkg/repos/runtimes/golang/golang.go index f86fa88d..5cba4779 100644 --- a/pkg/repos/runtimes/golang/golang.go +++ b/pkg/repos/runtimes/golang/golang.go @@ -17,6 +17,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "github.com/gptscript-ai/gptscript/pkg/config" "github.com/gptscript-ai/gptscript/pkg/debugcmd" @@ -34,6 +35,8 @@ const downloadURL = "https://go.dev/dl/" type Runtime struct { // version something like "1.22.1" Version string + + runtimeSetupLock sync.Mutex } func (r *Runtime) ID() string { @@ -97,19 +100,6 @@ type tag struct { } `json:"commit"` } -func GetLatestTag(tool types.Tool) (string, error) { - r, ok, err := getLatestRelease(tool) - if err != nil { - return "", err - } - - if !ok { - return "", fmt.Errorf("failed to get latest release for %s", tool.Name) - } - - return r.label, nil -} - func getLatestRelease(tool types.Tool) (*release, bool, error) { if tool.Source.Repo == nil || !strings.HasPrefix(tool.Source.Repo.Root, "https://github.com/") { return nil, false, nil @@ -355,6 +345,9 @@ func (r *Runtime) binDir(rel string) string { } func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) { + r.runtimeSetupLock.Lock() + defer r.runtimeSetupLock.Unlock() + url, sha, err := r.getReleaseAndDigest() if err != nil { return "", err diff --git a/pkg/repos/runtimes/node/node.go b/pkg/repos/runtimes/node/node.go index 4d73c13b..53b77ca2 100644 --- a/pkg/repos/runtimes/node/node.go +++ b/pkg/repos/runtimes/node/node.go @@ -12,6 +12,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "github.com/gptscript-ai/gptscript/pkg/debugcmd" runtimeEnv "github.com/gptscript-ai/gptscript/pkg/env" @@ -34,6 +35,8 @@ type Runtime struct { Version string // If true this is the version that will be used for python or python3 Default bool + + runtimeSetupLock sync.Mutex } func (r *Runtime) ID() string { @@ -175,6 +178,9 @@ func (r *Runtime) binDir(rel string) (string, error) { } func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) { + r.runtimeSetupLock.Lock() + defer r.runtimeSetupLock.Unlock() + url, sha, err := r.getReleaseAndDigest() if err != nil { return "", err diff --git a/pkg/repos/runtimes/python/python.go b/pkg/repos/runtimes/python/python.go index ee4bf571..4aebe0cf 100644 --- a/pkg/repos/runtimes/python/python.go +++ b/pkg/repos/runtimes/python/python.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "runtime" + "sync" "github.com/gptscript-ai/gptscript/pkg/debugcmd" runtimeEnv "github.com/gptscript-ai/gptscript/pkg/env" @@ -42,6 +43,8 @@ type Runtime struct { Version string // If true this is the version that will be used for python or python3 Default bool + + runtimeSetupLock sync.Mutex } func (r *Runtime) ID() string { @@ -234,6 +237,9 @@ func (r *Runtime) setupUV(ctx context.Context, tmp string) error { } func (r *Runtime) getRuntime(ctx context.Context, cwd string) (string, error) { + r.runtimeSetupLock.Lock() + defer r.runtimeSetupLock.Unlock() + url, sha, err := r.getReleaseAndDigest() if err != nil { return "", err diff --git a/pkg/runner/credentials.go b/pkg/runner/credentials.go deleted file mode 100644 index d2fbb00e..00000000 --- a/pkg/runner/credentials.go +++ /dev/null @@ -1,43 +0,0 @@ -package runner - -import ( - "fmt" - "os" - "strings" -) - -// parseCredentialOverrides parses a string of credential overrides that the user provided as a command line arg. -// The format of credential overrides can be one of two things: -// cred1:ENV1,ENV2 (direct mapping of environment variables) -// cred1:ENV1=VALUE1,ENV2=VALUE2 (key-value pairs) -// -// This function turns it into a map[string]map[string]string like this: -// -// { -// "cred1": { -// "ENV1": "VALUE1", -// "ENV2": "VALUE2", -// } -// } -func parseCredentialOverrides(overrides []string) (map[string]map[string]string, error) { - credentialOverrides := make(map[string]map[string]string) - - for _, o := range overrides { - credName, envs, found := strings.Cut(o, ":") - if !found { - return nil, fmt.Errorf("invalid credential override: %s", o) - } - envMap := make(map[string]string) - for _, env := range strings.Split(envs, ",") { - key, value, found := strings.Cut(env, "=") - if !found { - // User just passed an env var name as the key, so look up the value. - value = os.Getenv(key) - } - envMap[key] = value - } - credentialOverrides[credName] = envMap - } - - return credentialOverrides, nil -} diff --git a/pkg/runner/credentials_test.go b/pkg/runner/credentials_test.go index c568d6be..74fa9353 100644 --- a/pkg/runner/credentials_test.go +++ b/pkg/runner/credentials_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" + "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/stretchr/testify/require" ) @@ -119,7 +120,7 @@ func TestParseCredentialOverrides(t *testing.T) { _ = os.Setenv(k, v) } - out, err := parseCredentialOverrides(tc.in) + out, err := credentials.ParseCredentialOverrides(tc.in) if tc.expectErr { require.Error(t, err) return diff --git a/pkg/runner/input.go b/pkg/runner/input.go index 23228813..04d17cc3 100644 --- a/pkg/runner/input.go +++ b/pkg/runner/input.go @@ -15,15 +15,21 @@ func (r *Runner) handleInput(callCtx engine.Context, monitor Monitor, env []stri } for _, inputToolRef := range inputToolRefs { + if callCtx.Program.ToolSet[inputToolRef.ToolID].IsNoop() { + continue + } data := map[string]any{} _ = json.Unmarshal([]byte(input), &data) data["input"] = input - inputData, err := json.Marshal(data) + + inputArgs, err := argsForFilters(callCtx.Program, inputToolRef, &State{ + StartInput: &input, + }, data) if err != nil { return "", fmt.Errorf("failed to marshal input: %w", err) } - res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, inputToolRef.ToolID, string(inputData), "", engine.InputToolCategory) + res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, inputToolRef.ToolID, inputArgs, "", engine.InputToolCategory) if err != nil { return "", err } diff --git a/pkg/runner/output.go b/pkg/runner/output.go index e5fe849d..e48891fd 100644 --- a/pkg/runner/output.go +++ b/pkg/runner/output.go @@ -4,12 +4,48 @@ import ( "encoding/json" "errors" "fmt" + "maps" + "strings" "github.com/gptscript-ai/gptscript/pkg/engine" "github.com/gptscript-ai/gptscript/pkg/types" ) -func (r *Runner) handleOutput(callCtx engine.Context, monitor Monitor, env []string, state *State, retErr error) (*State, error) { +func argsForFilters(prg *types.Program, tool types.ToolReference, startState *State, filterDefinedInput map[string]any) (string, error) { + startInput := "" + if startState.ResumeInput != nil { + startInput = *startState.ResumeInput + } else if startState.StartInput != nil { + startInput = *startState.StartInput + } + + parsedArgs, err := types.GetToolRefInput(prg, tool, startInput) + if err != nil { + return "", err + } + + argData := map[string]any{} + if strings.HasPrefix(parsedArgs, "{") { + if err := json.Unmarshal([]byte(parsedArgs), &argData); err != nil { + return "", fmt.Errorf("failed to unmarshal parsedArgs for filter: %w", err) + } + } else if _, hasInput := filterDefinedInput["input"]; parsedArgs != "" && !hasInput { + argData["input"] = parsedArgs + } + + resultData := map[string]any{} + maps.Copy(resultData, filterDefinedInput) + maps.Copy(resultData, argData) + + result, err := json.Marshal(resultData) + if err != nil { + return "", fmt.Errorf("failed to marshal resultData for filter: %w", err) + } + + return string(result), nil +} + +func (r *Runner) handleOutput(callCtx engine.Context, monitor Monitor, env []string, startState, state *State, retErr error) (*State, error) { outputToolRefs, err := callCtx.Tool.GetToolsByType(callCtx.Program, types.ToolTypeOutput) if err != nil { return nil, err @@ -40,7 +76,10 @@ func (r *Runner) handleOutput(callCtx engine.Context, monitor Monitor, env []str } for _, outputToolRef := range outputToolRefs { - inputData, err := json.Marshal(map[string]any{ + if callCtx.Program.ToolSet[outputToolRef.ToolID].IsNoop() { + continue + } + inputData, err := argsForFilters(callCtx.Program, outputToolRef, startState, map[string]any{ "output": output, "continuation": continuation, "chat": callCtx.Tool.Chat, @@ -48,7 +87,7 @@ func (r *Runner) handleOutput(callCtx engine.Context, monitor Monitor, env []str if err != nil { return nil, fmt.Errorf("marshaling input for output filter: %w", err) } - res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, outputToolRef.ToolID, string(inputData), "", engine.OutputToolCategory) + res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, outputToolRef.ToolID, inputData, "", engine.OutputToolCategory) if err != nil { return nil, err } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 7ac9fae0..200c453b 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -14,6 +14,7 @@ import ( context2 "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/engine" + "github.com/gptscript-ai/gptscript/pkg/mcp" "github.com/gptscript-ai/gptscript/pkg/types" "golang.org/x/exp/maps" ) @@ -37,6 +38,11 @@ type Options struct { CredentialOverrides []string `usage:"-"` Sequential bool `usage:"-"` Authorizer AuthorizerFunc `usage:"-"` + MCPRunner engine.MCPRunner `usage:"-"` +} + +type RunOptions struct { + UserCancel <-chan struct{} } type AuthorizerResponse struct { @@ -65,6 +71,9 @@ func Complete(opts ...Options) (result Options) { if opt.CredentialOverrides != nil { result.CredentialOverrides = append(result.CredentialOverrides, opt.CredentialOverrides...) } + if opt.MCPRunner != nil { + result.MCPRunner = opt.MCPRunner + } } return } @@ -83,6 +92,9 @@ func complete(opts ...Options) Options { if result.Authorizer == nil { result.Authorizer = DefaultAuthorizer } + if result.MCPRunner == nil { + result.MCPRunner = mcp.DefaultRunner + } return result } @@ -95,6 +107,7 @@ type Runner struct { credOverrides []string credStore credentials.CredentialStore sequential bool + mcpRunner engine.MCPRunner } func New(client engine.Model, credStore credentials.CredentialStore, opts ...Options) (*Runner, error) { @@ -109,6 +122,7 @@ func New(client engine.Model, credStore credentials.CredentialStore, opts ...Opt credStore: credStore, sequential: opt.Sequential, auth: opt.Authorizer, + mcpRunner: opt.MCPRunner, } if opt.StartPort != 0 { @@ -130,7 +144,7 @@ type ChatResponse struct { type ChatState interface{} -func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Program, env []string, input string) (resp ChatResponse, err error) { +func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Program, env []string, input string, opts RunOptions) (resp ChatResponse, err error) { var state *State defer func() { @@ -167,7 +181,7 @@ func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Progra monitor.Stop(ctx, resp.Content, err) }() - callCtx, err := engine.NewContext(ctx, &prg, input) + callCtx, err := engine.NewContext(ctx, &prg, input, opts.UserCancel) if err != nil { return resp, err } @@ -210,8 +224,8 @@ func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Progra }, nil } -func (r *Runner) Run(ctx context.Context, prg types.Program, env []string, input string) (output string, err error) { - resp, err := r.Chat(ctx, nil, prg, env, input) +func (r *Runner) Run(ctx context.Context, prg types.Program, env []string, input string, opts RunOptions) (output string, err error) { + resp, err := r.Chat(ctx, nil, prg, env, input, opts) if err != nil { return "", err } @@ -245,89 +259,6 @@ var ( EventTypeRunFinish EventType = "runFinish" ) -func getToolRefInput(prg *types.Program, ref types.ToolReference, input string) (string, error) { - if ref.Arg == "" { - return "", nil - } - - targetArgs := prg.ToolSet[ref.ToolID].Arguments - targetKeys := map[string]string{} - - if ref.Arg == "*" { - return input, nil - } - - if targetArgs == nil { - return "", nil - } - - for targetKey := range targetArgs.Properties { - targetKeys[strings.ToLower(targetKey)] = targetKey - } - - inputMap := map[string]interface{}{} - outputMap := map[string]interface{}{} - - _ = json.Unmarshal([]byte(input), &inputMap) - - fields := strings.Fields(ref.Arg) - - for i := 0; i < len(fields); i++ { - field := fields[i] - if field == "and" { - continue - } - if field == "as" { - i++ - continue - } - - var ( - keyName string - val any - ) - - if strings.HasPrefix(field, "$") { - key := strings.TrimPrefix(field, "$") - key = strings.TrimPrefix(key, "{") - key = strings.TrimSuffix(key, "}") - val = inputMap[key] - } else { - val = field - } - - if len(fields) > i+1 && fields[i+1] == "as" { - keyName = strings.ToLower(fields[i+2]) - } - - if len(targetKeys) == 0 { - return "", fmt.Errorf("can not assign arg to context because target tool [%s] has no defined args", ref.ToolID) - } - - if keyName == "" { - if len(targetKeys) != 1 { - return "", fmt.Errorf("can not assign arg to context because target tool [%s] has does not have one args. You must use \"as\" syntax to map the arg to a key %v", ref.ToolID, targetKeys) - } - for k := range targetKeys { - keyName = k - } - } - - if targetKey, ok := targetKeys[strings.ToLower(keyName)]; ok { - outputMap[targetKey] = val - } else { - return "", fmt.Errorf("can not assign arg to context because target tool [%s] has does not args [%s]", ref.ToolID, keyName) - } - } - - if len(outputMap) == 0 { - return "", nil - } - - output, err := json.Marshal(outputMap) - return string(output), err -} - func (r *Runner) getContext(callCtx engine.Context, state *State, monitor Monitor, env []string, input string) (result []engine.InputContext, _ error) { toolRefs, err := callCtx.Tool.GetToolsByType(callCtx.Program, types.ToolTypeContext) if err != nil { @@ -340,7 +271,7 @@ func (r *Runner) getContext(callCtx engine.Context, state *State, monitor Monito continue } - contextInput, err := getToolRefInput(callCtx.Program, toolRef, input) + contextInput, err := types.GetToolRefInput(callCtx.Program, toolRef, input) if err != nil { return nil, err } @@ -405,6 +336,7 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en e := engine.Engine{ Model: r.c, + MCPRunner: r.mcpRunner, RuntimeManager: runtimeWithLogger(callCtx, monitor, r.runtimeManager), Progress: progress, Env: env, @@ -425,6 +357,7 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en msg = "Tool call request has been denied" } return &State{ + StartInput: &input, Continuation: &engine.Return{ Result: &msg, }, @@ -438,6 +371,7 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en } return &State{ + StartInput: &input, Continuation: ret, }, nil } @@ -447,6 +381,8 @@ type State struct { ContinuationToolID string `json:"continuationToolID,omitempty"` Result *string `json:"result,omitempty"` + StartInput *string `json:"startInput,omitempty"` + ResumeInput *string `json:"resumeInput,omitempty"` SubCalls []SubCallResult `json:"subCalls,omitempty"` SubCallID string `json:"subCallID,omitempty"` @@ -485,14 +421,13 @@ func (s State) ContinuationContent() (string, error) { return "", fmt.Errorf("illegal state: no result message found in chat response") } -type Needed struct { - Content string `json:"content,omitempty"` - Input string `json:"input,omitempty"` -} - func (r *Runner) resume(callCtx engine.Context, monitor Monitor, env []string, state *State) (retState *State, retErr error) { + handleOutput := true + defer func() { - retState, retErr = r.handleOutput(callCtx, monitor, env, retState, retErr) + if handleOutput { + retState, retErr = r.handleOutput(callCtx, monitor, env, state, retState, retErr) + } }() if state.Continuation == nil { @@ -519,21 +454,33 @@ func (r *Runner) resume(callCtx engine.Context, monitor Monitor, env []string, s if state.Continuation.Result != nil && len(state.Continuation.Calls) == 0 && state.SubCallID == "" && state.ResumeInput == nil { progressClose() - monitor.Event(Event{ - Time: time.Now(), - CallContext: callCtx.GetCallContext(), - Type: EventTypeCallFinish, - Content: getEventContent(*state.Continuation.Result, callCtx), - }) if callCtx.Tool.Chat { - return &State{ + retState = &State{ Continuation: state.Continuation, ContinuationToolID: callCtx.Tool.ID, - }, nil + } + } else { + retState = &State{ + Result: state.Continuation.Result, + } } - return &State{ - Result: state.Continuation.Result, - }, nil + handleOutput = false + retState, retErr = r.handleOutput(callCtx, monitor, env, state, retState, nil) + if retErr == nil { + var content string + if retState.Continuation != nil && retState.Continuation.Result != nil { + content = *retState.Continuation.Result + } else if retState.Result != nil { + content = *retState.Result + } + monitor.Event(Event{ + Time: time.Now(), + CallContext: callCtx.GetCallContext(), + Type: EventTypeCallFinish, + Content: getEventContent(content, callCtx), + }) + } + return retState, retErr } monitor.Event(Event{ @@ -588,6 +535,7 @@ func (r *Runner) resume(callCtx engine.Context, monitor Monitor, env []string, s e := engine.Engine{ Model: r.c, + MCPRunner: r.mcpRunner, RuntimeManager: runtimeWithLogger(callCtx, monitor, r.runtimeManager), Progress: progress, Env: env, @@ -719,8 +667,22 @@ func (r *Runner) newDispatcher(ctx context.Context) dispatcher { return newParallelDispatcher(ctx) } -func (r *Runner) subCalls(callCtx engine.Context, monitor Monitor, env []string, state *State, toolCategory engine.ToolCategory) (_ *State, callResults []SubCallResult, _ error) { - var resultLock sync.Mutex +func idForToolCall(id string, state *engine.Return) string { + if state == nil || state.State == nil { + return id + } + tc, ok := state.State.Pending[id] + if !ok || tc.Index == nil { + return id + } + return fmt.Sprintf("%03d", *tc.Index) +} + +func (r *Runner) subCalls(callCtx engine.Context, monitor Monitor, env []string, state *State, toolCategory engine.ToolCategory) (*State, []SubCallResult, error) { + var ( + resultLock sync.Mutex + callResults []SubCallResult + ) if state.Continuation != nil { callCtx.LastReturn = state.Continuation @@ -734,8 +696,6 @@ func (r *Runner) subCalls(callCtx engine.Context, monitor Monitor, env []string, for _, subCall := range state.SubCalls { if subCall.CallID == state.SubCallID { found = true - subState := *subCall.State - subState.ResumeInput = state.ResumeInput result, err := r.subCallResume(callCtx.Ctx, callCtx, monitor, env, subCall.ToolID, subCall.CallID, subCall.State.WithResumeInput(state.ResumeInput), toolCategory) if err != nil { return nil, nil, err @@ -761,7 +721,9 @@ func (r *Runner) subCalls(callCtx engine.Context, monitor Monitor, env []string, // Sort the id so if sequential the results are predictable ids := maps.Keys(state.Continuation.Calls) - sort.Strings(ids) + sort.Slice(ids, func(i, j int) bool { + return idForToolCall(ids[i], state.Continuation) < idForToolCall(ids[j], state.Continuation) + }) for _, id := range ids { call := state.Continuation.Calls[id] @@ -822,7 +784,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env err error ) if r.credOverrides != nil { - credOverrides, err = parseCredentialOverrides(r.credOverrides) + credOverrides, err = credentials.ParseCredentialOverrides(r.credOverrides) if err != nil { return nil, fmt.Errorf("failed to parse credential overrides: %w", err) } @@ -830,7 +792,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env var nearestExpiration *time.Time for _, ref := range credToolRefs { - toolName, credentialAlias, args, err := types.ParseCredentialArgs(ref.Reference, callCtx.Input) + toolName, credentialAlias, checkParam, args, err := types.ParseCredentialArgs(ref.Reference, callCtx.Input) if err != nil { return nil, fmt.Errorf("failed to parse credential tool %q: %w", ref.Reference, err) } @@ -860,11 +822,6 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env refresh bool ) - rm := runtimeWithLogger(callCtx, monitor, r.runtimeManager) - if err := rm.EnsureCredentialHelpers(callCtx.Ctx); err != nil { - return nil, fmt.Errorf("failed to setup credential helpers: %w", err) - } - // Only try to look up the cred if the tool is on GitHub or has an alias. // If it is a GitHub tool and has an alias, the alias overrides the tool name, so we use it as the credential name. if isGitHubTool(toolName) && credentialAlias == "" { @@ -875,7 +832,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env } else if credentialAlias != "" { c, exists, err = r.credStore.Get(callCtx.Ctx, credentialAlias) if err != nil { - return nil, fmt.Errorf("failed to get credentials for tool %s: %w", credentialAlias, err) + return nil, fmt.Errorf("failed to get credential %s: %w", credentialAlias, err) } } @@ -885,9 +842,10 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env // If the credential doesn't already exist in the store, run the credential tool in order to get the value, // and save it in the store. - if !exists || c.IsExpired() { + if !exists || c.IsExpired() || checkParam != c.CheckParam { // If the existing credential is expired, we need to provide it to the cred tool through the environment. - if exists && c.IsExpired() { + // If the check parameter is different, then we don't refresh. We should re-auth below. + if exists && c.IsExpired() && checkParam == c.CheckParam { refresh = true credJSON, err := json.Marshal(c) if err != nil { @@ -908,7 +866,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, ref.ToolID, input, "", engine.CredentialToolCategory) if err != nil { - return nil, fmt.Errorf("failed to run credential tool %s: %w", ref.Reference, err) + return nil, err } if res.Result == nil { @@ -919,6 +877,10 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env continue } + if strings.HasSuffix(*res.Result, engine.AbortedSuffix) { + continue + } + if err := json.Unmarshal([]byte(*res.Result), &resultCredential); err != nil { return nil, fmt.Errorf("failed to unmarshal credential tool %s response: %w", ref.Reference, err) } diff --git a/pkg/runner/runtimemanager.go b/pkg/runner/runtimemanager.go index ed191d15..1c293215 100644 --- a/pkg/runner/runtimemanager.go +++ b/pkg/runner/runtimemanager.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - "github.com/gptscript-ai/gptscript/pkg/config" "github.com/gptscript-ai/gptscript/pkg/engine" "github.com/gptscript-ai/gptscript/pkg/mvl" "github.com/gptscript-ai/gptscript/pkg/types" @@ -40,11 +39,3 @@ func (r runtimeManagerLogger) Infof(msg string, args ...any) { func (r runtimeManagerLogger) GetContext(ctx context.Context, tool types.Tool, cmd, env []string) (string, []string, error) { return r.rm.GetContext(mvl.WithInfo(ctx, r), tool, cmd, env) } - -func (r runtimeManagerLogger) EnsureCredentialHelpers(ctx context.Context) error { - return r.rm.EnsureCredentialHelpers(mvl.WithInfo(ctx, r)) -} - -func (r runtimeManagerLogger) SetUpCredentialHelpers(_ context.Context, _ *config.CLIConfig) error { - panic("not implemented") -} diff --git a/pkg/sdkserver/credentials.go b/pkg/sdkserver/credentials.go index b0246621..adf86bc7 100644 --- a/pkg/sdkserver/credentials.go +++ b/pkg/sdkserver/credentials.go @@ -7,30 +7,34 @@ import ( "net/http" "slices" - "github.com/gptscript-ai/gptscript/pkg/config" gcontext "github.com/gptscript-ai/gptscript/pkg/context" "github.com/gptscript-ai/gptscript/pkg/credentials" ) -func (s *server) initializeCredentialStore(ctx context.Context, credCtxs []string) (credentials.CredentialStore, error) { - cfg, err := config.ReadCLIConfig(s.gptscriptOpts.OpenAI.ConfigFile) +func (s *server) initializeCredentialStore(_ context.Context, credCtxs []string) (credentials.CredentialStore, error) { + store, err := s.client.CredentialStoreFactory.NewStore(credCtxs) if err != nil { - return nil, fmt.Errorf("failed to read CLI config: %w", err) + return nil, fmt.Errorf("failed to initialize credential store: %w", err) } - if err := s.runtimeManager.SetUpCredentialHelpers(ctx, cfg); err != nil { - return nil, fmt.Errorf("failed to set up credential helpers: %w", err) - } - if err := s.runtimeManager.EnsureCredentialHelpers(ctx); err != nil { - return nil, fmt.Errorf("failed to ensure credential helpers: %w", err) - } + return store, nil +} + +func (s *server) recreateAllCredentials(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) - store, err := credentials.NewStore(cfg, s.runtimeManager, credCtxs, s.gptscriptOpts.Cache.CacheDir) + store, err := s.initializeCredentialStore(r.Context(), []string{credentials.AllCredentialContexts}) if err != nil { - return nil, fmt.Errorf("failed to initialize credential store: %w", err) + writeError(logger, w, http.StatusInternalServerError, err) + return } - return store, nil + if err := store.RecreateAll(r.Context()); err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to recreate all credentials: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": "All credentials recreated successfully"}) } func (s *server) listCredentials(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/sdkserver/datasets.go b/pkg/sdkserver/datasets.go new file mode 100644 index 00000000..b923490b --- /dev/null +++ b/pkg/sdkserver/datasets.go @@ -0,0 +1,281 @@ +package sdkserver + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + + gcontext "github.com/gptscript-ai/gptscript/pkg/context" + "github.com/gptscript-ai/gptscript/pkg/gptscript" + "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/runner" +) + +func (s *server) getDatasetTool(req datasetRequest) string { + if req.DatasetTool != "" { + return req.DatasetTool + } + + return s.datasetTool +} + +type datasetRequest struct { + Input string `json:"input"` + DatasetTool string `json:"datasetTool"` + Env []string `json:"env"` +} + +func (r datasetRequest) validate(requireInput bool) error { + if requireInput && r.Input == "" { + return fmt.Errorf("input is required") + } else if len(r.Env) == 0 { + return fmt.Errorf("env is required") + } + return nil +} + +func (r datasetRequest) opts(o gptscript.Options) gptscript.Options { + opts := gptscript.Options{ + Cache: o.Cache, + Monitor: o.Monitor, + Runner: o.Runner, + } + for _, e := range r.Env { + v, ok := strings.CutPrefix(e, "GPTSCRIPT_WORKSPACE_ID=") + if ok { + opts.Workspace = v + } + } + return opts +} + +func (s *server) listDatasets(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + + var req datasetRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to decode request body: %w", err)) + return + } + + if err := req.validate(false); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + g, err := gptscript.New(r.Context(), req.opts(s.gptscriptOpts)) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to initialize gptscript: %w", err)) + return + } + defer g.Close(false) + + prg, err := loader.Program(r.Context(), s.getDatasetTool(req), "List Datasets", loader.Options{ + Cache: g.Cache, + }) + + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + result, err := g.Run(r.Context(), prg, s.getServerToolsEnv(req.Env), req.Input, runner.RunOptions{}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": result}) +} + +type addDatasetElementsArgs struct { + DatasetID string `json:"datasetID"` + Name string `json:"name"` + Description string `json:"description"` + Elements []struct { + Name string `json:"name"` + Description string `json:"description"` + Contents string `json:"contents"` + BinaryContents []byte `json:"binaryContents"` + } `json:"elements"` +} + +func (a addDatasetElementsArgs) validate() error { + if len(a.Elements) == 0 { + return fmt.Errorf("elements is required") + } + return nil +} + +func (s *server) addDatasetElements(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + + var req datasetRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to decode request body: %w", err)) + return + } + + if err := req.validate(true); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + g, err := gptscript.New(r.Context(), req.opts(s.gptscriptOpts)) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to initialize gptscript: %w", err)) + return + } + defer g.Close(false) + + var args addDatasetElementsArgs + if err := json.Unmarshal([]byte(req.Input), &args); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to unmarshal input: %w", err)) + return + } + + if err := args.validate(); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + prg, err := loader.Program(r.Context(), s.getDatasetTool(req), "Add Elements", loader.Options{ + Cache: g.Cache, + }) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + result, err := g.Run(r.Context(), prg, s.getServerToolsEnv(req.Env), req.Input, runner.RunOptions{}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": result}) +} + +type listDatasetElementsArgs struct { + DatasetID string `json:"datasetID"` +} + +func (a listDatasetElementsArgs) validate() error { + if a.DatasetID == "" { + return fmt.Errorf("datasetID is required") + } + return nil +} + +func (s *server) listDatasetElements(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + + var req datasetRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to decode request body: %w", err)) + return + } + + if err := req.validate(true); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + g, err := gptscript.New(r.Context(), req.opts(s.gptscriptOpts)) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to initialize gptscript: %w", err)) + return + } + defer g.Close(false) + + var args listDatasetElementsArgs + if err := json.Unmarshal([]byte(req.Input), &args); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to unmarshal input: %w", err)) + return + } + + if err := args.validate(); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + prg, err := loader.Program(r.Context(), s.getDatasetTool(req), "List Elements", loader.Options{ + Cache: g.Cache, + }) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + result, err := g.Run(r.Context(), prg, s.getServerToolsEnv(req.Env), req.Input, runner.RunOptions{}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": result}) +} + +type getDatasetElementArgs struct { + DatasetID string `json:"datasetID"` + Name string `json:"name"` +} + +func (a getDatasetElementArgs) validate() error { + if a.DatasetID == "" { + return fmt.Errorf("datasetID is required") + } else if a.Name == "" { + return fmt.Errorf("name is required") + } + return nil +} + +func (s *server) getDatasetElement(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + + var req datasetRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to decode request body: %w", err)) + return + } + + if err := req.validate(true); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + g, err := gptscript.New(r.Context(), req.opts(s.gptscriptOpts)) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to initialize gptscript: %w", err)) + return + } + defer g.Close(false) + + var args getDatasetElementArgs + if err := json.Unmarshal([]byte(req.Input), &args); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("failed to unmarshal input: %w", err)) + return + } + + if err := args.validate(); err != nil { + writeError(logger, w, http.StatusBadRequest, err) + return + } + + prg, err := loader.Program(r.Context(), s.getDatasetTool(req), "Get Element", loader.Options{ + Cache: g.Cache, + }) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + result, err := g.Run(r.Context(), prg, s.getServerToolsEnv(req.Env), req.Input, runner.RunOptions{}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": result}) +} diff --git a/pkg/sdkserver/routes.go b/pkg/sdkserver/routes.go index fc69a08c..52a06994 100644 --- a/pkg/sdkserver/routes.go +++ b/pkg/sdkserver/routes.go @@ -3,9 +3,7 @@ package sdkserver import ( "encoding/json" "fmt" - "io" "net/http" - "os" "sort" "strings" "sync" @@ -26,16 +24,22 @@ import ( ) type server struct { - gptscriptOpts gptscript.Options - address, token string - client *gptscript.GPTScript - events *broadcaster.Broadcaster[event] + gptscriptOpts gptscript.Options + address, token string + datasetTool, workspaceTool string + serverToolsEnv []string + client *gptscript.GPTScript + mcpLoader loader.MCPLoader + events *broadcaster.Broadcaster[event] runtimeManager engine.RuntimeManager lock sync.RWMutex waitingToConfirm map[string]chan runner.AuthorizerResponse waitingToPrompt map[string]chan map[string]string + + runningLock sync.Mutex + running map[string]chan struct{} } func (s *server) addRoutes(mux *http.ServeMux) { @@ -52,6 +56,7 @@ func (s *server) addRoutes(mux *http.ServeMux) { mux.HandleFunc("POST /run", s.execHandler) mux.HandleFunc("POST /evaluate", s.execHandler) + mux.HandleFunc("POST /abort/{run_id}", s.abort) mux.HandleFunc("POST /load", s.load) @@ -66,6 +71,25 @@ func (s *server) addRoutes(mux *http.ServeMux) { mux.HandleFunc("POST /credentials/create", s.createCredential) mux.HandleFunc("POST /credentials/reveal", s.revealCredential) mux.HandleFunc("POST /credentials/delete", s.deleteCredential) + mux.HandleFunc("POST /credentials/recreate-all", s.recreateAllCredentials) + + mux.HandleFunc("POST /datasets", s.listDatasets) + mux.HandleFunc("POST /datasets/list-elements", s.listDatasetElements) + mux.HandleFunc("POST /datasets/get-element", s.getDatasetElement) + mux.HandleFunc("POST /datasets/add-elements", s.addDatasetElements) + + mux.HandleFunc("POST /workspaces/create", s.createWorkspace) + mux.HandleFunc("POST /workspaces/delete", s.deleteWorkspace) + mux.HandleFunc("POST /workspaces/list", s.listWorkspaceContents) + mux.HandleFunc("POST /workspaces/remove-all-with-prefix", s.removeAllWithPrefixInWorkspace) + mux.HandleFunc("POST /workspaces/write-file", s.writeFileInWorkspace) + mux.HandleFunc("POST /workspaces/delete-file", s.removeFileInWorkspace) + mux.HandleFunc("POST /workspaces/read-file", s.readFileInWorkspace) + mux.HandleFunc("POST /workspaces/read-file-with-revision", s.readFileWithRevisionInWorkspace) + mux.HandleFunc("POST /workspaces/stat-file", s.statFileInWorkspace) + mux.HandleFunc("POST /workspaces/list-revisions", s.listRevisions) + mux.HandleFunc("POST /workspaces/get-revision", s.getRevisionForFileInWorkspace) + mux.HandleFunc("POST /workspaces/delete-revision", s.deleteRevisionForFileInWorkspace) } // health just provides an endpoint for checking whether the server is running and accessible. @@ -91,7 +115,7 @@ func (s *server) listTools(w http.ResponseWriter, r *http.Request) { // Don't print instructions tool.Instructions = "" - lines = append(lines, tool.String()) + lines = append(lines, tool.Print()) } writeResponse(logger, w, map[string]any{"stdout": strings.Join(lines, "\n---\n")}) @@ -130,34 +154,43 @@ func (s *server) listModels(w http.ResponseWriter, r *http.Request) { return } - writeResponse(logger, w, map[string]any{"stdout": strings.Join(out, "\n")}) + writeResponse(logger, w, map[string]any{"stdout": out}) } // execHandler is a general handler for executing tools with gptscript. This is mainly responsible for parsing the request body. // Then the options and tool are passed to the process function. func (s *server) execHandler(w http.ResponseWriter, r *http.Request) { logger := gcontext.GetLogger(r.Context()) - body, err := io.ReadAll(r.Body) - if err != nil { - writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to read request body: %w", err)) - return - } reqObject := new(toolOrFileRequest) - if err := json.Unmarshal(body, reqObject); err != nil { + if err := json.NewDecoder(r.Body).Decode(reqObject); err != nil { writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) return } ctx := gserver.ContextWithNewRunID(r.Context()) runID := gserver.RunIDFromContext(ctx) + cancel := make(chan struct{}) + s.runningLock.Lock() + s.running[runID] = cancel + s.runningLock.Unlock() + + defer func() { + s.runningLock.Lock() + // Need to check if the cancel is still in map. In case when user abort, the channel will be deleted from map and closed already, and closing it again will panic + _, ok := s.running[runID] + if ok { + close(cancel) + } + delete(s.running, runID) + s.runningLock.Unlock() + }() // Ensure chat state is not empty. if reqObject.ChatState == "" { reqObject.ChatState = "null" } - reqObject.Env = append(os.Environ(), reqObject.Env...) // Don't overwrite the PromptURLEnvVar if it is already set in the environment. var promptTokenAlreadySet bool for _, env := range reqObject.Env { @@ -202,7 +235,30 @@ func (s *server) execHandler(w http.ResponseWriter, r *http.Request) { opts.Runner.Authorizer = s.authorize } - s.execAndStream(ctx, programLoader, logger, w, opts, reqObject.ChatState, reqObject.Input, reqObject.SubTool, def) + s.execAndStream(ctx, programLoader, logger, w, opts, reqObject.ChatState, reqObject.Input, reqObject.SubTool, def, cancel) +} + +// abort will abort the run in a way such that the chat state will be returned. +func (s *server) abort(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + runID := r.PathValue("run_id") + if runID == "" { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("run_id is required")) + return + } + + s.runningLock.Lock() + cancel := s.running[runID] + delete(s.running, runID) + s.runningLock.Unlock() + + if cancel == nil { + writeResponse(logger, w, "run not found") + return + } + + close(cancel) + writeResponse(logger, w, "run aborted") } // load will load the file and return the corresponding Program. @@ -217,21 +273,31 @@ func (s *server) load(w http.ResponseWriter, r *http.Request) { logger.Debugf("parsing file: file=%s, content=%s", reqObject.File, reqObject.Content) var ( - prg types.Program - err error - cache = s.client.Cache + prg types.Program + err error + + ctx = r.Context() ) if reqObject.DisableCache { - cache = nil + ctx = cache.WithNoCache(ctx) } if reqObject.Content != "" { - prg, err = loader.ProgramFromSource(r.Context(), reqObject.Content, reqObject.SubTool, loader.Options{Cache: cache}) + prg, err = loader.ProgramFromSource(ctx, reqObject.Content, reqObject.SubTool, loader.Options{ + Cache: s.client.Cache, + MCPLoader: s.mcpLoader, + }) } else if reqObject.File != "" { - prg, err = loader.Program(r.Context(), reqObject.File, reqObject.SubTool, loader.Options{Cache: cache}) + prg, err = loader.Program(ctx, reqObject.File, reqObject.SubTool, loader.Options{ + Cache: s.client.Cache, + MCPLoader: s.mcpLoader, + }) } else { - prg, err = loader.ProgramFromSource(r.Context(), reqObject.ToolDefs.String(), reqObject.SubTool, loader.Options{Cache: cache}) + prg, err = loader.ProgramFromSource(ctx, reqObject.ToolDefs.String(), reqObject.SubTool, loader.Options{ + Cache: s.client.Cache, + MCPLoader: s.mcpLoader, + }) } if err != nil { writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) @@ -287,5 +353,5 @@ func (s *server) fmtDocument(w http.ResponseWriter, r *http.Request) { return } - writeResponse(logger, w, map[string]string{"stdout": doc.String()}) + writeResponse(logger, w, map[string]string{"stdout": doc.Print()}) } diff --git a/pkg/sdkserver/run.go b/pkg/sdkserver/run.go index b6b5a049..a2c0d505 100644 --- a/pkg/sdkserver/run.go +++ b/pkg/sdkserver/run.go @@ -24,7 +24,7 @@ func loaderWithLocation(f loaderFunc, loc string) loaderFunc { } } -func (s *server) execAndStream(ctx context.Context, programLoader loaderFunc, logger mvl.Logger, w http.ResponseWriter, opts gptscript.Options, chatState, input, subTool string, toolDef fmt.Stringer) { +func (s *server) execAndStream(ctx context.Context, programLoader loaderFunc, logger mvl.Logger, w http.ResponseWriter, opts gptscript.Options, chatState, input, subTool string, toolDef fmt.Stringer, cancel <-chan struct{}) { g, err := gptscript.New(ctx, s.gptscriptOpts, opts) if err != nil { writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to initialize gptscript: %w", err)) @@ -32,7 +32,15 @@ func (s *server) execAndStream(ctx context.Context, programLoader loaderFunc, lo } defer g.Close(false) - prg, err := programLoader(ctx, toolDef.String(), subTool, loader.Options{Cache: g.Cache}) + defaultModel := opts.OpenAI.DefaultModel + if defaultModel == "" { + defaultModel = s.gptscriptOpts.OpenAI.DefaultModel + } + prg, err := programLoader(ctx, toolDef.String(), subTool, loader.Options{ + Cache: g.Cache, + DefaultModel: defaultModel, + MCPLoader: s.mcpLoader, + }) if err != nil { writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) return @@ -44,7 +52,9 @@ func (s *server) execAndStream(ctx context.Context, programLoader loaderFunc, lo defer events.Close() go func() { - run, err := g.Chat(ctx, chatState, prg, opts.Env, input) + run, err := g.Chat(ctx, chatState, prg, opts.Env, input, runner.RunOptions{ + UserCancel: cancel, + }) if err != nil { errChan <- err } else { @@ -54,21 +64,19 @@ func (s *server) execAndStream(ctx context.Context, programLoader loaderFunc, lo close(programOutput) }() - processEventStreamOutput(ctx, logger, w, gserver.RunIDFromContext(ctx), events.C, programOutput, errChan) + processEventStreamOutput(logger, w, gserver.RunIDFromContext(ctx), events.C, programOutput, errChan) } // processEventStreamOutput will stream the events of the tool to the response as server sent events. // If an error occurs, then an event with the error will also be sent. -func processEventStreamOutput(ctx context.Context, logger mvl.Logger, w http.ResponseWriter, id string, events <-chan event, output <-chan runner.ChatResponse, errChan chan error) { +func processEventStreamOutput(logger mvl.Logger, w http.ResponseWriter, id string, events <-chan event, output <-chan runner.ChatResponse, errChan chan error) { run := newRun(id) setStreamingHeaders(w) - streamEvents(ctx, logger, w, run, events) + streamEvents(logger, w, run, events) - var out runner.ChatResponse select { - case <-ctx.Done(): - case out = <-output: + case out := <-output: run.processStdout(out) writeServerSentEvent(logger, w, map[string]any{ @@ -76,52 +84,32 @@ func processEventStreamOutput(ctx context.Context, logger mvl.Logger, w http.Res }) case err := <-errChan: writeServerSentEvent(logger, w, map[string]any{ - "stderr": fmt.Sprintf("failed to run: %v", err), + "stderr": err.Error(), }) } // Now that we have received all events, send the DONE event. - _, err := w.Write([]byte("data: [DONE]\n\n")) - if err == nil { - if f, ok := w.(http.Flusher); ok { - f.Flush() - } - } + writeServerSentEvent(logger, w, "[DONE]") logger.Debugf("wrote DONE event") } // streamEvents will stream the events of the tool to the response as server sent events. -func streamEvents(ctx context.Context, logger mvl.Logger, w http.ResponseWriter, run *runInfo, events <-chan event) { +func streamEvents(logger mvl.Logger, w http.ResponseWriter, run *runInfo, events <-chan event) { logger.Debugf("receiving events") - for { - select { - case <-ctx.Done(): - logger.Debugf("context canceled while receiving events") - go func() { - //nolint:revive - for range events { - } - }() - return - case e, ok := <-events: - if ok && e.RunID != run.ID { - continue - } - - if !ok { - logger.Debugf("done receiving events") - return - } - - writeServerSentEvent(logger, w, run.process(e)) - - if e.Type == runner.EventTypeRunFinish { - logger.Debugf("finished receiving events") - return - } + for e := range events { + if e.RunID != run.ID { + continue + } + + writeServerSentEvent(logger, w, run.process(e)) + + if e.Type == runner.EventTypeRunFinish { + break } } + + logger.Debugf("done receiving events") } func writeResponse(logger mvl.Logger, w http.ResponseWriter, v any) { @@ -147,7 +135,7 @@ func writeError(logger mvl.Logger, w http.ResponseWriter, code int, err error) { b, err := json.Marshal(resp) if err != nil { - _, _ = w.Write([]byte(fmt.Sprintf(`{"stderr": "%s"}`, err.Error()))) + _, _ = fmt.Fprintf(w, `{"stderr": "%s"}`, err.Error()) return } @@ -164,7 +152,7 @@ func writeServerSentEvent(logger mvl.Logger, w http.ResponseWriter, event any) { return } - _, err = w.Write([]byte(fmt.Sprintf("data: %s\n\n", ev))) + _, err = fmt.Fprintf(w, "data: %s\n\n", ev) if err == nil { if f, ok := w.(http.Flusher); ok { f.Flush() diff --git a/pkg/sdkserver/server.go b/pkg/sdkserver/server.go index 0a68f0fa..7b0e4c1a 100644 --- a/pkg/sdkserver/server.go +++ b/pkg/sdkserver/server.go @@ -16,6 +16,8 @@ import ( "github.com/google/uuid" "github.com/gptscript-ai/broadcaster" "github.com/gptscript-ai/gptscript/pkg/gptscript" + "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/mcp" "github.com/gptscript-ai/gptscript/pkg/mvl" "github.com/gptscript-ai/gptscript/pkg/repos/runtimes" "github.com/gptscript-ai/gptscript/pkg/runner" @@ -26,9 +28,12 @@ import ( type Options struct { gptscript.Options - ListenAddress string - Debug bool - DisableServerErrorLogging bool + MCPLoader loader.MCPLoader + ListenAddress string + DatasetTool, WorkspaceTool string + ServerToolsEnv []string + Debug bool + DisableServerErrorLogging bool } // Run will start the server and block until the server is shut down. @@ -90,7 +95,7 @@ func run(ctx context.Context, listener net.Listener, opts Options) error { } events := broadcaster.New[event]() - opts.Options.Runner.MonitorFactory = NewSessionFactory(events) + opts.Runner.MonitorFactory = NewSessionFactory(events) go events.Start(ctx) token := uuid.NewString() @@ -104,21 +109,28 @@ func run(ctx context.Context, listener net.Listener, opts Options) error { } s := &server{ - gptscriptOpts: opts.Options, - address: listener.Addr().String(), - token: token, + gptscriptOpts: opts.Options, + address: listener.Addr().String(), + token: token, + datasetTool: opts.DatasetTool, + workspaceTool: opts.WorkspaceTool, + serverToolsEnv: opts.ServerToolsEnv, + client: g, + mcpLoader: opts.MCPLoader, events: events, - runtimeManager: runtimes.Default(opts.Options.Cache.CacheDir), // TODO - do we always want to use runtimes.Default here? + runtimeManager: runtimes.Default(opts.Cache.CacheDir, opts.SystemToolsDir), waitingToConfirm: make(map[string]chan runner.AuthorizerResponse), waitingToPrompt: make(map[string]chan map[string]string), + running: make(map[string]chan struct{}), } defer s.close() - s.addRoutes(http.DefaultServeMux) + mux := http.NewServeMux() + s.addRoutes(mux) httpServer := &http.Server{ - Handler: apply(http.DefaultServeMux, + Handler: apply(mux, contentType("application/json"), addRequestID, addLogger, @@ -157,13 +169,29 @@ func complete(opts ...Options) Options { for _, opt := range opts { result.Options = gptscript.Complete(result.Options, opt.Options) result.ListenAddress = types.FirstSet(opt.ListenAddress, result.ListenAddress) + result.DatasetTool = types.FirstSet(opt.DatasetTool, result.DatasetTool) + result.WorkspaceTool = types.FirstSet(opt.WorkspaceTool, result.WorkspaceTool) result.Debug = types.FirstSet(opt.Debug, result.Debug) result.DisableServerErrorLogging = types.FirstSet(opt.DisableServerErrorLogging, result.DisableServerErrorLogging) + result.MCPLoader = types.FirstSet(opt.MCPLoader, result.MCPLoader) } if result.ListenAddress == "" { result.ListenAddress = "127.0.0.1:0" } + if result.WorkspaceTool == "" { + result.WorkspaceTool = "github.com/gptscript-ai/workspace-provider" + } + if result.DatasetTool == "" { + result.DatasetTool = "github.com/gptscript-ai/datasets" + } + if len(result.ServerToolsEnv) == 0 { + result.ServerToolsEnv = os.Environ() + } + if result.MCPLoader == nil { + result.MCPLoader = mcp.DefaultLoader + } + return result } diff --git a/pkg/sdkserver/types.go b/pkg/sdkserver/types.go index a4332557..278a8c78 100644 --- a/pkg/sdkserver/types.go +++ b/pkg/sdkserver/types.go @@ -1,8 +1,8 @@ package sdkserver import ( + "encoding/json" "maps" - "strings" "time" "github.com/gptscript-ai/gptscript/pkg/cache" @@ -30,15 +30,12 @@ const ( type toolDefs []types.ToolDef func (t toolDefs) String() string { - s := new(strings.Builder) - for i, tool := range t { - s.WriteString(tool.String()) - if i != len(t)-1 { - s.WriteString("\n\n---\n\n") - } + data, err := json.Marshal(t) + if err != nil { + panic(err) } - return s.String() + return "#!GPTSCRIPT" + string(data) } type ( diff --git a/pkg/sdkserver/workspaces.go b/pkg/sdkserver/workspaces.go new file mode 100644 index 00000000..f1846051 --- /dev/null +++ b/pkg/sdkserver/workspaces.go @@ -0,0 +1,484 @@ +package sdkserver + +import ( + "encoding/json" + "fmt" + "net/http" + + gcontext "github.com/gptscript-ai/gptscript/pkg/context" + "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/runner" +) + +func (s *server) getWorkspaceTool(req workspaceCommonRequest) string { + if req.WorkspaceTool != "" { + return req.WorkspaceTool + } + + return s.workspaceTool +} + +type workspaceCommonRequest struct { + ID string `json:"id"` + WorkspaceTool string `json:"workspaceTool"` + Env []string `json:"env"` +} + +type createWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + ProviderType string `json:"providerType"` + FromWorkspaceIDs []string `json:"fromWorkspaceIDs"` +} + +func (s *server) getServerToolsEnv(env []string) []string { + return append(s.serverToolsEnv, env...) +} + +func (s *server) createWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject createWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Create Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + if reqObject.ProviderType == "" { + reqObject.ProviderType = "directory" + } + + b, err := json.Marshal(map[string]any{ + "provider": reqObject.ProviderType, + "fromWorkspaceIDs": reqObject.FromWorkspaceIDs, + }) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to marshal request body: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + string(b), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type deleteWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` +} + +func (s *server) deleteWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject deleteWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Delete Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s"}`, + reqObject.ID, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type listWorkspaceContentsRequest struct { + workspaceCommonRequest `json:",inline"` + ID string `json:"id"` + Prefix string `json:"prefix"` +} + +func (s *server) listWorkspaceContents(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject listWorkspaceContentsRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "List Workspace Contents", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "ls_prefix": "%s"}`, + reqObject.ID, reqObject.Prefix, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type removeAllWithPrefixInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + Prefix string `json:"prefix"` +} + +func (s *server) removeAllWithPrefixInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject removeAllWithPrefixInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Remove All With Prefix In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "prefix": "%s"}`, + reqObject.ID, reqObject.Prefix, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type writeFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` + Contents string `json:"contents"` + CreateRevision *bool `json:"createRevision"` + LatestRevisionID string `json:"latestRevisionID"` +} + +func (s *server) writeFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject writeFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Write File In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s", "body": "%s", "create_revision": %t, "latest_revision_id": "%s"}`, + reqObject.ID, reqObject.FilePath, reqObject.Contents, reqObject.CreateRevision == nil || *reqObject.CreateRevision, reqObject.LatestRevisionID, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type rmFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` +} + +func (s *server) removeFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject rmFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Remove File In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s"}`, + reqObject.ID, reqObject.FilePath, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type readFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` +} + +func (s *server) readFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject readFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Read File In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s"}`, + reqObject.ID, reqObject.FilePath, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +func (s *server) readFileWithRevisionInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject readFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Read File With Revision In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s", "with_latest_revision_id": "true"}`, + reqObject.ID, reqObject.FilePath, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type statFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` + WithLatestRevisionID bool `json:"withLatestRevisionID"` +} + +func (s *server) statFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject statFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Stat File In Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s", "with_latest_revision_id": "%v"}`, + reqObject.ID, reqObject.FilePath, reqObject.WithLatestRevisionID, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type listRevisionsRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` +} + +func (s *server) listRevisions(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject listRevisionsRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "List Revisions for File in Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s"}`, + reqObject.ID, reqObject.FilePath, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type getRevisionForFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` + RevisionID string `json:"revisionID"` +} + +func (s *server) getRevisionForFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject getRevisionForFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Get a Revision for File in Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s", "revision_id": "%s"}`, + reqObject.ID, reqObject.FilePath, reqObject.RevisionID, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} + +type deleteRevisionForFileInWorkspaceRequest struct { + workspaceCommonRequest `json:",inline"` + FilePath string `json:"filePath"` + RevisionID string `json:"revisionID"` +} + +func (s *server) deleteRevisionForFileInWorkspace(w http.ResponseWriter, r *http.Request) { + logger := gcontext.GetLogger(r.Context()) + var reqObject deleteRevisionForFileInWorkspaceRequest + if err := json.NewDecoder(r.Body).Decode(&reqObject); err != nil { + writeError(logger, w, http.StatusBadRequest, fmt.Errorf("invalid request body: %w", err)) + return + } + + prg, err := loader.Program(r.Context(), s.getWorkspaceTool(reqObject.workspaceCommonRequest), "Delete a Revision for File in Workspace", loader.Options{Cache: s.client.Cache}) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to load program: %w", err)) + return + } + + out, err := s.client.Run( + r.Context(), + prg, + s.getServerToolsEnv(reqObject.Env), + fmt.Sprintf( + `{"workspace_id": "%s", "file_path": "%s", "revision_id": "%s"}`, + reqObject.ID, reqObject.FilePath, reqObject.RevisionID, + ), + runner.RunOptions{}, + ) + if err != nil { + writeError(logger, w, http.StatusInternalServerError, fmt.Errorf("failed to run program: %w", err)) + return + } + + writeResponse(logger, w, map[string]any{"stdout": out}) +} diff --git a/pkg/system/prompt.go b/pkg/system/prompt.go index 6b1815fd..04497854 100644 --- a/pkg/system/prompt.go +++ b/pkg/system/prompt.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "github.com/getkin/kin-openapi/openapi3" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) // Suffix is default suffix of gptscript files @@ -26,26 +26,22 @@ You don't move to the next step until you have a result. // to just send pure text but the interface required JSON (as that is the fundamental interface of tools in OpenAI) var DefaultPromptParameter = "defaultPromptParameter" -var DefaultToolSchema = openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{ - DefaultPromptParameter: &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "Prompt to send to the tool. This may be an instruction or question.", - Type: &openapi3.Types{"string"}, - }, +var DefaultToolSchema = jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + DefaultPromptParameter: { + Description: "Prompt to send to the tool. This may be an instruction or question.", + Type: "string", }, }, } -var DefaultChatSchema = openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{ - DefaultPromptParameter: &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "Prompt to send to the assistant. This may be an instruction or question.", - Type: &openapi3.Types{"string"}, - }, +var DefaultChatSchema = jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + DefaultPromptParameter: { + Description: "Prompt to send to the assistant. This may be an instruction or question.", + Type: "string", }, }, } diff --git a/pkg/tests/judge/judge.go b/pkg/tests/judge/judge.go index eae12c2e..26464386 100644 --- a/pkg/tests/judge/judge.go +++ b/pkg/tests/judge/judge.go @@ -40,6 +40,8 @@ After making a determination, respond with a JSON object that conforms to the fo ] } +If you determine actual and expected are not equivalent, include a diff of the parts of actual and expected that are not equivalent in the reasoning field of your response. + Your responses are concise and include only the json object described above. ` @@ -84,10 +86,10 @@ func New[T any](client *openai.Client) (*Judge[T], error) { } func (j *Judge[T]) Equal(ctx context.Context, expected, actual T, criteria string) (equal bool, reasoning string, err error) { - comparisonJSON, err := json.MarshalIndent(&comparison[T]{ + comparisonJSON, err := json.Marshal(&comparison[T]{ Expected: expected, Actual: actual, - }, "", " ") + }) if err != nil { return false, "", fmt.Errorf("failed to marshal judge testcase JSON: %w", err) } @@ -110,7 +112,7 @@ func (j *Judge[T]) Equal(ctx context.Context, expected, actual T, criteria strin }, }, } - response, err := j.client.CreateChatCompletion(ctx, request) + response, err := j.client.CreateChatCompletion(ctx, request, nil) if err != nil { return false, "", fmt.Errorf("failed to create chat completion request: %w", err) } diff --git a/pkg/tests/runner2_test.go b/pkg/tests/runner2_test.go index 93899c84..9668a98a 100644 --- a/pkg/tests/runner2_test.go +++ b/pkg/tests/runner2_test.go @@ -2,10 +2,15 @@ package tests import ( "context" + "encoding/json" + "runtime" "testing" "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/runner" "github.com/gptscript-ai/gptscript/pkg/tests/tester" + "github.com/gptscript-ai/gptscript/pkg/types" + "github.com/hexops/autogold/v2" "github.com/stretchr/testify/require" ) @@ -26,10 +31,10 @@ echo This is the input: ${GPTSCRIPT_INPUT} `, "") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1", runner.RunOptions{}) r.AssertStep(t, resp, err) - resp, err = r.Chat(context.Background(), resp.State, prg, nil, "input 2") + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "input 2", runner.RunOptions{}) r.AssertStep(t, resp, err) } @@ -52,7 +57,7 @@ name: realcontext Yo dawg`, "") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1", runner.RunOptions{}) r.AssertStep(t, resp, err) } @@ -74,8 +79,484 @@ echo ${FOO}:${INPUT} `, "") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, `{"foo":"123"}`) + resp, err := r.Chat(context.Background(), nil, prg, nil, `{"foo":"123"}`, runner.RunOptions{}) r.AssertStep(t, resp, err) - resp, err = r.Chat(context.Background(), nil, prg, nil, `"foo":"123"}`) + resp, err = r.Chat(context.Background(), nil, prg, nil, `"foo":"123"}`, runner.RunOptions{}) + r.AssertStep(t, resp, err) +} + +func TestShareCreds(t *testing.T) { + r := tester.NewRunner(t) + prg, err := loader.ProgramFromSource(context.Background(), ` +creds: foo + +#!/bin/bash +echo $CRED +echo $CRED2 + +--- +name: foo +share credentials: bar + +--- +name: bar +share credentials: baz + +#!/bin/bash +echo '{"env": {"CRED": "that worked"}}' + +--- +name: baz + +#!/bin/bash +echo '{"env": {"CRED2": "that also worked"}}' +`, "") + require.NoError(t, err) + + resp, err := r.Chat(context.Background(), nil, prg, nil, "", runner.RunOptions{}) + r.AssertStep(t, resp, err) +} + +func TestFilterArgs(t *testing.T) { + r := tester.NewRunner(t) + prg, err := loader.ProgramFromSource(context.Background(), ` +inputfilters: input with ${Foo} +inputfilters: input with foo +inputfilters: input with * +outputfilters: output with * +outputfilters: output with foo +outputfilters: output with ${Foo} +params: Foo: a description + +#!/bin/bash +echo ${FOO} + +--- +name: input +params: notfoo: a description + +#!/bin/bash +echo "${GPTSCRIPT_INPUT}" + +--- +name: output +params: notfoo: a description + +#!/bin/bash +echo "${GPTSCRIPT_INPUT}" +`, "") + require.NoError(t, err) + + resp, err := r.Chat(context.Background(), nil, prg, nil, `{"foo":"baz", "start": true}`, runner.RunOptions{}) + r.AssertStep(t, resp, err) + + data := map[string]any{} + err = json.Unmarshal([]byte(resp.Content), &data) + require.NoError(t, err) + + autogold.Expect(map[string]interface{}{ + "chat": false, + "continuation": false, + "notfoo": "baz", + "output": `{"chat":false,"continuation":false,"notfoo":"foo","output":"{\"chat\":false,\"continuation\":false,\"foo\":\"baz\",\"input\":\"{\\\"foo\\\":\\\"baz\\\",\\\"input\\\":\\\"{\\\\\\\"foo\\\\\\\":\\\\\\\"baz\\\\\\\", \\\\\\\"start\\\\\\\": true}\\\",\\\"notfoo\\\":\\\"baz\\\",\\\"start\\\":true}\\n\",\"notfoo\":\"foo\",\"output\":\"baz\\n\",\"start\":true}\n"} +`, + }).Equal(t, data) + + val := data["output"].(string) + data = map[string]any{} + err = json.Unmarshal([]byte(val), &data) + require.NoError(t, err) + autogold.Expect(map[string]interface{}{ + "chat": false, + "continuation": false, + "notfoo": "foo", + "output": `{"chat":false,"continuation":false,"foo":"baz","input":"{\"foo\":\"baz\",\"input\":\"{\\\"foo\\\":\\\"baz\\\", \\\"start\\\": true}\",\"notfoo\":\"baz\",\"start\":true}\n","notfoo":"foo","output":"baz\n","start":true} +`, + }).Equal(t, data) + + val = data["output"].(string) + data = map[string]any{} + err = json.Unmarshal([]byte(val), &data) + require.NoError(t, err) + autogold.Expect(map[string]interface{}{ + "chat": false, + "continuation": false, + "foo": "baz", "input": `{"foo":"baz","input":"{\"foo\":\"baz\", \"start\": true}","notfoo":"baz","start":true} +`, + "notfoo": "foo", + "output": "baz\n", + "start": true, + }).Equal(t, data) + + val = data["input"].(string) + data = map[string]any{} + err = json.Unmarshal([]byte(val), &data) + require.NoError(t, err) + autogold.Expect(map[string]interface{}{ + "foo": "baz", + "input": `{"foo":"baz", "start": true}`, + "notfoo": "baz", + "start": true, + }).Equal(t, data) + + val = data["input"].(string) + data = map[string]any{} + err = json.Unmarshal([]byte(val), &data) + require.NoError(t, err) + autogold.Expect(map[string]interface{}{"foo": "baz", "start": true}).Equal(t, data) +} + +func TestMCPLoad(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Skipping test on Windows") + } + + r := tester.NewRunner(t) + prg, err := loader.ProgramFromSource(t.Context(), ` +name: mcp + +#!mcp + +{ + "mcpServers": { + "sqlite": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "-v", + "mcp-test:/mcp", + "mcp/sqlite@sha256:007ccae941a6f6db15b26ee41d92edda50ce157176d9273449e8b3f51d979c70", + "--db-path", + "/mcp/test.db" + ] + } + } +} +`, "") + require.NoError(t, err) + + autogold.Expect(types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + Name: "mcp", + Description: "sqlite", + ModelName: "gpt-4o", + Export: []string{ + "read_query", + "write_query", + "create_table", + "list_tables", + "describe_table", + "append_insight", + }, + }, + MetaData: map[string]string{"bundle": "true"}, + }, + ID: "inline:mcp", + ToolMapping: map[string][]types.ToolReference{ + "append_insight": {{ + Reference: "append_insight", + ToolID: "inline:append_insight", + }}, + "create_table": {{ + Reference: "create_table", + ToolID: "inline:create_table", + }}, + "describe_table": {{ + Reference: "describe_table", + ToolID: "inline:describe_table", + }}, + "list_tables": {{ + Reference: "list_tables", + ToolID: "inline:list_tables", + }}, + "read_query": {{ + Reference: "read_query", + ToolID: "inline:read_query", + }}, + "write_query": {{ + Reference: "write_query", + ToolID: "inline:write_query", + }}, + }, + LocalTools: map[string]string{ + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query", + }, + Source: types.ToolSource{Location: "inline"}, + WorkingDir: ".", + }).Equal(t, prg.ToolSet[prg.EntryToolID]) + autogold.Expect(7).Equal(t, len(prg.ToolSet[prg.EntryToolID].LocalTools)) + data, _ := json.MarshalIndent(prg.ToolSet, "", " ") + autogold.Expect(`{ + "inline:append_insight": { + "name": "append_insight", + "description": "Add a business insight to the memo", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object", + "required": [ + "insight" + ], + "properties": { + "insight": { + "type": "string", + "description": "Business insight discovered from data analysis" + } + } + }, + "instructions": "#!sys.mcp.invoke.append_insight e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:append_insight", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:create_table": { + "name": "create_table", + "description": "Create a new table in the SQLite database", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string", + "description": "CREATE TABLE SQL statement" + } + } + }, + "instructions": "#!sys.mcp.invoke.create_table e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:create_table", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:describe_table": { + "name": "describe_table", + "description": "Get the schema information for a specific table", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object", + "required": [ + "table_name" + ], + "properties": { + "table_name": { + "type": "string", + "description": "Name of the table to describe" + } + } + }, + "instructions": "#!sys.mcp.invoke.describe_table e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:describe_table", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:list_tables": { + "name": "list_tables", + "description": "List all tables in the SQLite database", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object" + }, + "instructions": "#!sys.mcp.invoke.list_tables e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:list_tables", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:mcp": { + "name": "mcp", + "description": "sqlite", + "modelName": "gpt-4o", + "internalPrompt": null, + "export": [ + "read_query", + "write_query", + "create_table", + "list_tables", + "describe_table", + "append_insight" + ], + "metaData": { + "bundle": "true" + }, + "id": "inline:mcp", + "toolMapping": { + "append_insight": [ + { + "reference": "append_insight", + "toolID": "inline:append_insight" + } + ], + "create_table": [ + { + "reference": "create_table", + "toolID": "inline:create_table" + } + ], + "describe_table": [ + { + "reference": "describe_table", + "toolID": "inline:describe_table" + } + ], + "list_tables": [ + { + "reference": "list_tables", + "toolID": "inline:list_tables" + } + ], + "read_query": [ + { + "reference": "read_query", + "toolID": "inline:read_query" + } + ], + "write_query": [ + { + "reference": "write_query", + "toolID": "inline:write_query" + } + ] + }, + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:read_query": { + "name": "read_query", + "description": "Execute a SELECT query on the SQLite database", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string", + "description": "SELECT SQL query to execute" + } + } + }, + "instructions": "#!sys.mcp.invoke.read_query e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:read_query", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + }, + "inline:write_query": { + "name": "write_query", + "description": "Execute an INSERT, UPDATE, or DELETE query on the SQLite database", + "modelName": "gpt-4o", + "internalPrompt": null, + "arguments": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string", + "description": "SQL query to execute" + } + } + }, + "instructions": "#!sys.mcp.invoke.write_query e592cc0c9483290685611ba70bd8595829cc794f7eae0419eabb3388bf0d3529", + "id": "inline:write_query", + "localTools": { + "append_insight": "inline:append_insight", + "create_table": "inline:create_table", + "describe_table": "inline:describe_table", + "list_tables": "inline:list_tables", + "mcp": "inline:mcp", + "read_query": "inline:read_query", + "write_query": "inline:write_query" + }, + "source": { + "location": "inline" + }, + "workingDir": "." + } +}`).Equal(t, string(data)) + + prg.EntryToolID = prg.ToolSet[prg.EntryToolID].LocalTools["read_query"] + resp, err := r.Chat(context.Background(), nil, prg, nil, `{"query": "SELECT 1"}`, runner.RunOptions{}) r.AssertStep(t, resp, err) } diff --git a/pkg/tests/runner_test.go b/pkg/tests/runner_test.go index 18871ed6..bda3a5b6 100644 --- a/pkg/tests/runner_test.go +++ b/pkg/tests/runner_test.go @@ -7,11 +7,13 @@ import ( "encoding/json" "io" "os" + "os/exec" "runtime" "testing" "github.com/gptscript-ai/gptscript/pkg/engine" "github.com/gptscript-ai/gptscript/pkg/loader" + "github.com/gptscript-ai/gptscript/pkg/runner" "github.com/gptscript-ai/gptscript/pkg/tests/tester" "github.com/gptscript-ai/gptscript/pkg/types" "github.com/hexops/autogold/v2" @@ -26,6 +28,17 @@ func toJSONString(t *testing.T, v interface{}) string { return string(x) } +func TestMain(m *testing.M) { + cmd := exec.CommandContext(context.Background(), "go", "build", "-o", "bin/gptscript", "../../main.go") + if err := cmd.Run(); err != nil { + panic(err) + } + + os.Setenv("NANOBOT_BIN", "bin/gptscript") + defer os.Unsetenv("NANOBOT_BIN") + m.Run() +} + func TestAsterick(t *testing.T) { r := tester.NewRunner(t) p, err := r.Load("") @@ -143,7 +156,7 @@ func TestDualSubChat(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "User 1") + resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "User 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -157,7 +170,7 @@ func TestDualSubChat(t *testing.T) { }, }) - resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 2") + resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 2", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -168,7 +181,7 @@ func TestDualSubChat(t *testing.T) { Text: "Assistant 3", }) - resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 3") + resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 3", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -184,7 +197,7 @@ func TestDualSubChat(t *testing.T) { Text: "And we're done", }) - resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 4") + resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 4", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.True(t, resp.Done) @@ -213,7 +226,7 @@ func TestContextSubChat(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - _, err = r.Chat(context.Background(), nil, prg, os.Environ(), "User 1") + _, err = r.Chat(context.Background(), nil, prg, os.Environ(), "User 1", runner.RunOptions{}) autogold.Expect("invalid state: context tool [testdata/TestContextSubChat/test.gpt:subtool] can not result in a continuation").Equal(t, err.Error()) } @@ -232,7 +245,7 @@ func TestSubChat(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "Hello") + resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "Hello", runner.RunOptions{}) require.NoError(t, err) autogold.Expect(`{ @@ -251,13 +264,13 @@ func TestSubChat(t *testing.T) { "toolID": "testdata/TestSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -357,7 +370,7 @@ func TestSubChat(t *testing.T) { } }`).Equal(t, toJSONString(t, resp)) - resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 1") + resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 1", runner.RunOptions{}) require.NoError(t, err) autogold.Expect(`{ @@ -376,13 +389,13 @@ func TestSubChat(t *testing.T) { "toolID": "testdata/TestSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -512,7 +525,7 @@ func TestChat(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "Hello") + resp, err := r.Chat(context.Background(), nil, prg, os.Environ(), "Hello", runner.RunOptions{}) require.NoError(t, err) autogold.Expect(`{ @@ -564,7 +577,7 @@ func TestChat(t *testing.T) { } }`).Equal(t, toJSONString(t, resp)) - resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 1") + resp, err = r.Chat(context.Background(), resp.State, prg, os.Environ(), "User 1", runner.RunOptions{}) require.NoError(t, err) autogold.Expect(`{ @@ -740,7 +753,7 @@ func TestAgentOnly(t *testing.T) { }, }) - resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -767,7 +780,7 @@ func TestAgents(t *testing.T) { }, }) - resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -785,14 +798,14 @@ func TestInput(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "You're stupid") + resp, err := r.Chat(context.Background(), nil, prg, nil, "You're stupid", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) autogold.Expect("TEST RESULT CALL: 1").Equal(t, resp.Content) autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step1")) - resp, err = r.Chat(context.Background(), resp.State, prg, nil, "You're ugly") + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "You're ugly", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -813,7 +826,7 @@ func TestOutput(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "Input 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -824,7 +837,7 @@ func TestOutput(t *testing.T) { r.RespondWith(tester.Result{ Text: "Response 2", }) - resp, err = r.Chat(context.Background(), resp.State, prg, nil, "Input 2") + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "Input 2", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -837,7 +850,7 @@ func TestOutput(t *testing.T) { Message: "Chat Done", }, }) - resp, err = r.Chat(context.Background(), resp.State, prg, nil, "Input 3") + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "Input 3", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.True(t, resp.Done) @@ -885,7 +898,7 @@ func TestSysContext(t *testing.T) { prg, err := r.Load("") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -977,7 +990,7 @@ tools: sys.ls, sys.read, sys.write `, "") require.NoError(t, err) - resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1") + resp, err := r.Chat(context.Background(), nil, prg, nil, "input 1", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) @@ -991,7 +1004,7 @@ tools: sys.ls, sys.write `, "") require.NoError(t, err) - resp, err = r.Chat(context.Background(), resp.State, prg, nil, "input 2") + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "input 2", runner.RunOptions{}) require.NoError(t, err) r.AssertResponded(t) assert.False(t, resp.Done) diff --git a/pkg/tests/smoke/smoke_test.go b/pkg/tests/smoke/smoke_test.go index a6d0ab2c..b7e50b37 100644 --- a/pkg/tests/smoke/smoke_test.go +++ b/pkg/tests/smoke/smoke_test.go @@ -82,8 +82,8 @@ func TestSmoke(t *testing.T) { expectedEvents, actualEvents, ` -- disregard differences in timestamps, generated IDs, natural language verbiage, and event order -- omit callProgress events from the comparison +- disregard differences in event order, timestamps, generated IDs, and natural language verbiage, grammar, and punctuation +- compare events with matching event types - the overall stream of events and set of tools called should roughly match - arguments passed in tool calls should be roughly the same - the final callFinish event should be semantically similar @@ -175,6 +175,11 @@ func getActualEvents(t *testing.T, eventsFile string) []event { var e event require.NoError(t, json.Unmarshal([]byte(line), &e)) + + if e.Type == runner.EventTypeCallProgress { + continue + } + events = append(events, e) } diff --git a/pkg/tests/smoke/testdata/Bob/claude-3-5-sonnet-20240620-expected.json b/pkg/tests/smoke/testdata/Bob/claude-3-5-sonnet-20240620-expected.json deleted file mode 100644 index 63673b21..00000000 --- a/pkg/tests/smoke/testdata/Bob/claude-3-5-sonnet-20240620-expected.json +++ /dev/null @@ -1,929 +0,0 @@ -[ - { - "time": "2024-07-02T19:39:41.734737-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:41.735252-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:42.643066-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:42.643356-04:00", - "callContext": { - "id": "1719963583", - "tool": { - "name": "Anthropic Claude3 Model Provider", - "description": "Model provider for Anthropic hosted Claude3 models", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:43.666188-04:00", - "callContext": { - "id": "1719963583", - "tool": { - "name": "Anthropic Claude3 Model Provider", - "description": "Model provider for Anthropic hosted Claude3 models", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callFinish", - "usage": {}, - "content": "http://127.0.0.1:10887" - }, - { - "time": "2024-07-02T19:39:43.666385-04:00", - "type": "runFinish", - "usage": {} - }, - { - "time": "2024-07-02T19:39:43.666475-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963584", - "usage": {}, - "chatRequest": { - "model": "claude-3-5-sonnet-20240620", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-02T19:39:43.66707-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963584", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-02T19:39:45.331397-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963584", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-02T19:39:45.332721-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963584", - "usage": {}, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - } - ], - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:45.332824-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolSubCalls": { - "toolu_01XLGhfvziYUf8rFoQEbvw4P": { - "toolID": "testdata/Bob/test.gpt:bob", - "input": "{\"question\": \"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-07-02T19:39:45.332869-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-02T19:39:45.487113-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callChat", - "chatCompletionId": "1719963585", - "usage": {}, - "chatRequest": { - "model": "claude-3-5-sonnet-20240620", - "messages": [ - { - "role": "system", - "content": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"" - }, - { - "role": "user", - "content": "{\"question\": \"how are you doing\"}" - } - ], - "temperature": 0 - } - }, - { - "time": "2024-07-02T19:39:45.487696-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callProgress", - "chatCompletionId": "1719963585", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-02T19:39:46.547634-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callProgress", - "chatCompletionId": "1719963585", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-07-02T19:39:46.549112-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callChat", - "chatCompletionId": "1719963585", - "usage": {}, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - } - ], - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:46.549192-04:00", - "callContext": { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963582" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-07-02T19:39:46.549253-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-07-02T19:39:46.710406-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963586", - "usage": {}, - "chatRequest": { - "model": "claude-3-5-sonnet-20240620", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "toolu_01XLGhfvziYUf8rFoQEbvw4P", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!", - "name": "bob", - "tool_call_id": "toolu_01XLGhfvziYUf8rFoQEbvw4P" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-02T19:39:46.710675-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963586", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-02T19:39:48.861353-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963586", - "usage": {}, - "content": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - }, - { - "time": "2024-07-02T19:39:48.862116-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963586", - "usage": {}, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - } - ], - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:48.862154-04:00", - "callContext": { - "id": "1719963582", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - }, - { - "time": "2024-07-02T19:39:48.862164-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/Bob/claude-3-7-sonnet-20250219-expected.json b/pkg/tests/smoke/testdata/Bob/claude-3-7-sonnet-20250219-expected.json new file mode 100644 index 00000000..618c84d5 --- /dev/null +++ b/pkg/tests/smoke/testdata/Bob/claude-3-7-sonnet-20250219-expected.json @@ -0,0 +1,603 @@ +[ + { + "time": "2024-10-14T18:59:12.228692-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:12.229038-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:13.520962-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:13.521331-04:00", + "callContext": { + "id": "1728946754", + "tool": { + "name": "Anthropic Claude3 Model Provider", + "description": "Model provider for Anthropic hosted Claude3 models", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "modelProvider": true, + "internalPrompt": null, + "credentials": [ + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" + ], + "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", + "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider", + "toolMapping": { + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ + { + "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", + "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/de2fada1c51a1dbb5c3e9ef268ea6740d1b52f80/tool.gpt:token" + } + ] + }, + "localTools": { + "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider" + }, + "source": { + "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt", + "lineNo": 1, + "repo": { + "VCS": "git", + "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", + "Path": "/", + "Name": "tool.gpt", + "Revision": "ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + } + }, + "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + }, + "currentAgent": {}, + "inputContext": null, + "toolCategory": "provider", + "displayText": "Running sys.daemon" + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:14.541348-04:00", + "callContext": { + "id": "1728946754", + "tool": { + "name": "Anthropic Claude3 Model Provider", + "description": "Model provider for Anthropic hosted Claude3 models", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "modelProvider": true, + "internalPrompt": null, + "credentials": [ + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" + ], + "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", + "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider", + "toolMapping": { + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ + { + "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", + "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/de2fada1c51a1dbb5c3e9ef268ea6740d1b52f80/tool.gpt:token" + } + ] + }, + "localTools": { + "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider" + }, + "source": { + "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt", + "lineNo": 1, + "repo": { + "VCS": "git", + "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", + "Path": "/", + "Name": "tool.gpt", + "Revision": "ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + } + }, + "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + }, + "currentAgent": {}, + "inputContext": null, + "toolCategory": "provider", + "displayText": "Running sys.daemon" + }, + "type": "callFinish", + "usage": {}, + "content": "http://127.0.0.1:10258" + }, + { + "time": "2024-10-14T18:59:14.541518-04:00", + "type": "runFinish", + "usage": {} + }, + { + "time": "2024-10-14T18:59:14.541566-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946755", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:17.304351-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946755", + "usage": {}, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "toolu_01KtYnAwnQ2cyRieDu98Jopb", + "function": { + "name": "bob", + "arguments": "{\"question\": \"how are you doing\"}" + } + } + } + ], + "usage": {} + } + }, + { + "time": "2024-10-14T18:59:17.304441-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "toolu_01KtYnAwnQ2cyRieDu98Jopb": { + "toolID": "testdata/Bob/test.gpt:bob", + "input": "{\"question\": \"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T18:59:17.304485-04:00", + "callContext": { + "id": "toolu_01KtYnAwnQ2cyRieDu98Jopb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946753" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\": \"how are you doing\"}" + }, + { + "time": "2024-10-14T18:59:17.394841-04:00", + "callContext": { + "id": "toolu_01KtYnAwnQ2cyRieDu98Jopb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946753" + }, + "type": "callChat", + "chatCompletionId": "1728946756", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:18.202926-04:00", + "callContext": { + "id": "toolu_01KtYnAwnQ2cyRieDu98Jopb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946753" + }, + "type": "callChat", + "chatCompletionId": "1728946756", + "usage": {}, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": {} + } + }, + { + "time": "2024-10-14T18:59:18.202988-04:00", + "callContext": { + "id": "toolu_01KtYnAwnQ2cyRieDu98Jopb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946753" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:18.203022-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T18:59:18.295164-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946757", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:19.737028-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946757", + "usage": {}, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": {} + } + }, + { + "time": "2024-10-14T18:59:19.737045-04:00", + "callContext": { + "id": "1728946753", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:19.737061-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/Bob/gpt-4-turbo-2024-04-09-expected.json b/pkg/tests/smoke/testdata/Bob/gpt-4-turbo-2024-04-09-expected.json deleted file mode 100644 index 01745e39..00000000 --- a/pkg/tests/smoke/testdata/Bob/gpt-4-turbo-2024-04-09-expected.json +++ /dev/null @@ -1,2348 +0,0 @@ -[ - { - "time": "2024-06-20T17:08:06.902669-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-06-20T17:08:06.902927-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-06-20T17:08:07.292073-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917688", - "usage": {}, - "chatRequest": { - "model": "gpt-4-turbo-2024-04-09", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T17:08:07.292172-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T17:08:28.052253-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T17:08:28.05243-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T17:08:28.1369-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T17:08:28.137013-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T17:08:28.244585-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T17:08:28.244731-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T17:08:28.32623-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing" - }, - { - "time": "2024-06-20T17:08:28.326358-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:28.326393-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:28.32645-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:28.326527-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917688", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:28.327843-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917688", - "usage": { - "promptTokens": 142, - "completionTokens": 17, - "totalTokens": 159 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 142, - "completionTokens": 17, - "totalTokens": 159 - } - } - }, - { - "time": "2024-06-20T17:08:28.328046-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "toolSubCalls": { - "call_vsmL6EoDecm0oVmUnHIvNkaL": { - "toolID": "testdata/Bob/test.gpt:bob", - "input": "{\"question\":\"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-06-20T17:08:28.328123-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:28.53993-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callChat", - "chatCompletionId": "1718917689", - "usage": {}, - "chatRequest": { - "model": "gpt-4-turbo-2024-04-09", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nWhen asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"" - }, - { - "role": "user", - "content": "{\"question\":\"how are you doing\"}" - } - ], - "temperature": 0 - } - }, - { - "time": "2024-06-20T17:08:28.540154-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T17:08:29.188341-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T17:08:29.188493-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T17:08:29.244545-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T17:08:29.244765-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T17:08:29.643951-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are" - }, - { - "time": "2024-06-20T17:08:29.644128-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are" - }, - { - "time": "2024-06-20T17:08:29.676951-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing," - }, - { - "time": "2024-06-20T17:08:29.677047-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing," - }, - { - "time": "2024-06-20T17:08:29.677123-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I" - }, - { - "time": "2024-06-20T17:08:29.677156-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm" - }, - { - "time": "2024-06-20T17:08:29.677184-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing" - }, - { - "time": "2024-06-20T17:08:29.677251-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great" - }, - { - "time": "2024-06-20T17:08:29.677288-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great" - }, - { - "time": "2024-06-20T17:08:29.727848-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T17:08:29.727983-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T17:08:29.782554-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.782738-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.782806-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.782839-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.782868-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callProgress", - "chatCompletionId": "1718917689", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.782988-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callChat", - "chatCompletionId": "1718917689", - "usage": { - "promptTokens": 124, - "completionTokens": 17, - "totalTokens": 141 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 124, - "completionTokens": 17, - "totalTokens": 141 - } - } - }, - { - "time": "2024-06-20T17:08:29.783047-04:00", - "callContext": { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917687" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:29.783089-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-06-20T17:08:29.966093-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917690", - "usage": {}, - "chatRequest": { - "model": "gpt-4-turbo-2024-04-09", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_vsmL6EoDecm0oVmUnHIvNkaL", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!", - "name": "bob", - "tool_call_id": "call_vsmL6EoDecm0oVmUnHIvNkaL" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T17:08:29.966449-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T17:08:30.668641-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm" - }, - { - "time": "2024-06-20T17:08:30.668802-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm" - }, - { - "time": "2024-06-20T17:08:30.668957-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm" - }, - { - "time": "2024-06-20T17:08:30.669089-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing" - }, - { - "time": "2024-06-20T17:08:30.669299-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow" - }, - { - "time": "2024-06-20T17:08:30.669392-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow" - }, - { - "time": "2024-06-20T17:08:30.716062-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI" - }, - { - "time": "2024-06-20T17:08:30.7162-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI" - }, - { - "time": "2024-06-20T17:08:30.743098-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:30.743401-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:30.74648-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:30.746568-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917690", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:30.746778-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917690", - "usage": { - "promptTokens": 183, - "completionTokens": 10, - "totalTokens": 193 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 183, - "completionTokens": 10, - "totalTokens": 193 - } - } - }, - { - "time": "2024-06-20T17:08:30.746856-04:00", - "callContext": { - "id": "1718917687", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:30.746896-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-05-13-expected.json b/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-05-13-expected.json deleted file mode 100644 index 4d22287d..00000000 --- a/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-05-13-expected.json +++ /dev/null @@ -1,2643 +0,0 @@ -[ - { - "time": "2024-06-20T16:58:11.3174-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-06-20T16:58:11.317644-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-06-20T16:58:11.638778-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917093", - "usage": {}, - "chatRequest": { - "model": "gpt-4o-2024-05-13", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T16:58:11.639016-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T16:58:12.564724-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T16:58:12.564911-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question" - }, - { - "time": "2024-06-20T16:58:12.564948-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question" - }, - { - "time": "2024-06-20T16:58:12.56497-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T16:58:12.564995-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how" - }, - { - "time": "2024-06-20T16:58:12.565045-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you" - }, - { - "time": "2024-06-20T16:58:12.565071-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you" - }, - { - "time": "2024-06-20T16:58:12.565112-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:12.565137-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:12.56516-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:12.565176-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917093", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:12.565397-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917093", - "usage": { - "promptTokens": 138, - "completionTokens": 17, - "totalTokens": 155 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 138, - "completionTokens": 17, - "totalTokens": 155 - } - } - }, - { - "time": "2024-06-20T16:58:12.565644-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "toolSubCalls": { - "call_rTx93wiIASDA8uk8XHwjVmCC": { - "toolID": "testdata/Bob/test.gpt:bob", - "input": "{\"question\":\"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-06-20T16:58:12.565728-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:12.72779-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callChat", - "chatCompletionId": "1718917094", - "usage": {}, - "chatRequest": { - "model": "gpt-4o-2024-05-13", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nWhen asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"" - }, - { - "role": "user", - "content": "{\"question\":\"how are you doing\"}" - } - ], - "temperature": 0 - } - }, - { - "time": "2024-06-20T16:58:12.728069-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T16:58:13.077264-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {} - }, - { - "time": "2024-06-20T16:58:13.077534-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T16:58:13.134723-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T16:58:13.134893-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T16:58:13.230591-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how" - }, - { - "time": "2024-06-20T16:58:13.230667-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how" - }, - { - "time": "2024-06-20T16:58:13.246344-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you" - }, - { - "time": "2024-06-20T16:58:13.246468-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing" - }, - { - "time": "2024-06-20T16:58:13.246531-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing" - }, - { - "time": "2024-06-20T16:58:13.246592-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm" - }, - { - "time": "2024-06-20T16:58:13.246645-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing" - }, - { - "time": "2024-06-20T16:58:13.246736-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great" - }, - { - "time": "2024-06-20T16:58:13.246796-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great" - }, - { - "time": "2024-06-20T16:58:13.30169-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T16:58:13.301837-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T16:58:13.31565-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T16:58:13.315798-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:13.315842-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:13.315879-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:13.315951-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callProgress", - "chatCompletionId": "1718917094", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:13.316055-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callChat", - "chatCompletionId": "1718917094", - "usage": { - "promptTokens": 122, - "completionTokens": 17, - "totalTokens": 139 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 122, - "completionTokens": 17, - "totalTokens": 139 - } - } - }, - { - "time": "2024-06-20T16:58:13.316115-04:00", - "callContext": { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917092" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:13.316171-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-06-20T16:58:13.533625-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917095", - "usage": {}, - "chatRequest": { - "model": "gpt-4o-2024-05-13", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_rTx93wiIASDA8uk8XHwjVmCC", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!", - "name": "bob", - "tool_call_id": "call_rTx93wiIASDA8uk8XHwjVmCC" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T16:58:13.53384-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T16:58:13.856349-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T16:58:13.856437-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T16:58:13.874317-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T16:58:13.874428-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T16:58:14.060243-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are" - }, - { - "time": "2024-06-20T16:58:14.060366-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are" - }, - { - "time": "2024-06-20T16:58:14.060418-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are" - }, - { - "time": "2024-06-20T16:58:14.060435-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you" - }, - { - "time": "2024-06-20T16:58:14.060456-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing" - }, - { - "time": "2024-06-20T16:58:14.060521-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing" - }, - { - "time": "2024-06-20T16:58:14.060555-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing" - }, - { - "time": "2024-06-20T16:58:14.060577-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing" - }, - { - "time": "2024-06-20T16:58:14.06061-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow" - }, - { - "time": "2024-06-20T16:58:14.060626-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow" - }, - { - "time": "2024-06-20T16:58:14.060686-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI" - }, - { - "time": "2024-06-20T16:58:14.06071-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T16:58:14.060727-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T16:58:14.060743-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:14.060788-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:14.060806-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917095", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:14.061001-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917095", - "usage": { - "promptTokens": 179, - "completionTokens": 18, - "totalTokens": 197 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 179, - "completionTokens": 18, - "totalTokens": 197 - } - } - }, - { - "time": "2024-06-20T16:58:14.061031-04:00", - "callContext": { - "id": "1718917092", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:14.061047-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-08-06-expected.json b/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-08-06-expected.json new file mode 100644 index 00000000..67d9742b --- /dev/null +++ b/pkg/tests/smoke/testdata/Bob/gpt-4o-2024-08-06-expected.json @@ -0,0 +1,538 @@ +[ + { + "time": "2024-10-14T18:59:07.751937-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:07.752324-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:07.75237-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946749", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:08.602251-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946749", + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "call_1nuYJNsE6SIQrXe4wyoMb8sh", + "function": { + "name": "bob", + "arguments": "{\"question\":\"how are you doing\"}" + } + } + } + ], + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + } + } + }, + { + "time": "2024-10-14T18:59:08.602522-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "call_1nuYJNsE6SIQrXe4wyoMb8sh": { + "toolID": "testdata/Bob/test.gpt:bob", + "input": "{\"question\":\"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T18:59:08.602683-04:00", + "callContext": { + "id": "call_1nuYJNsE6SIQrXe4wyoMb8sh", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946748" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\":\"how are you doing\"}" + }, + { + "time": "2024-10-14T18:59:08.602885-04:00", + "callContext": { + "id": "call_1nuYJNsE6SIQrXe4wyoMb8sh", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946748" + }, + "type": "callChat", + "chatCompletionId": "1728946750", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:09.291815-04:00", + "callContext": { + "id": "call_1nuYJNsE6SIQrXe4wyoMb8sh", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946748" + }, + "type": "callChat", + "chatCompletionId": "1728946750", + "usage": { + "promptTokens": 137, + "completionTokens": 16, + "totalTokens": 153 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 137, + "completionTokens": 16, + "totalTokens": 153 + } + } + }, + { + "time": "2024-10-14T18:59:09.291883-04:00", + "callContext": { + "id": "call_1nuYJNsE6SIQrXe4wyoMb8sh", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946748" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:09.291934-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T18:59:09.292559-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946751", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:10.065468-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946751", + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + } + } + }, + { + "time": "2024-10-14T18:59:10.065547-04:00", + "callContext": { + "id": "1728946748", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:10.065614-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/Bob/gpt-4o-mini-2024-07-18-expected.json b/pkg/tests/smoke/testdata/Bob/gpt-4o-mini-2024-07-18-expected.json new file mode 100644 index 00000000..e01dec10 --- /dev/null +++ b/pkg/tests/smoke/testdata/Bob/gpt-4o-mini-2024-07-18-expected.json @@ -0,0 +1,538 @@ +[ + { + "time": "2024-10-14T18:59:01.651525-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:01.651887-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T18:59:01.651929-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946743", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:05.893238-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946743", + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "call_mcJFw1oe8YYFRPD1ZvFR4uZb", + "function": { + "name": "bob", + "arguments": "{\"question\":\"how are you doing\"}" + } + } + } + ], + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + } + } + }, + { + "time": "2024-10-14T18:59:05.893515-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "call_mcJFw1oe8YYFRPD1ZvFR4uZb": { + "toolID": "testdata/Bob/test.gpt:bob", + "input": "{\"question\":\"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T18:59:05.893776-04:00", + "callContext": { + "id": "call_mcJFw1oe8YYFRPD1ZvFR4uZb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946742" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\":\"how are you doing\"}" + }, + { + "time": "2024-10-14T18:59:05.894101-04:00", + "callContext": { + "id": "call_mcJFw1oe8YYFRPD1ZvFR4uZb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946742" + }, + "type": "callChat", + "chatCompletionId": "1728946744", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:08.315365-04:00", + "callContext": { + "id": "call_mcJFw1oe8YYFRPD1ZvFR4uZb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946742" + }, + "type": "callChat", + "chatCompletionId": "1728946744", + "usage": { + "promptTokens": 137, + "completionTokens": 16, + "totalTokens": 153 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 137, + "completionTokens": 16, + "totalTokens": 153 + } + } + }, + { + "time": "2024-10-14T18:59:08.315556-04:00", + "callContext": { + "id": "call_mcJFw1oe8YYFRPD1ZvFR4uZb", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "When asked how I am doing, respond with the following exactly: \"Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!\" with ${QUESTION} replaced with the question text as given.", + "id": "testdata/Bob/test.gpt:bob", + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728946742" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:08.315661-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T18:59:08.315834-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946745", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T18:59:09.27109-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728946745", + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + } + } + }, + { + "time": "2024-10-14T18:59:09.271259-04:00", + "callContext": { + "id": "1728946742", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/Bob/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/Bob/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/Bob/test.gpt:", + "bob": "testdata/Bob/test.gpt:bob" + }, + "source": { + "location": "testdata/Bob/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/Bob" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing! I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T18:59:09.271406-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/Bob/mistral-large-2402-expected.json b/pkg/tests/smoke/testdata/Bob/mistral-large-2402-expected.json deleted file mode 100644 index 8730226a..00000000 --- a/pkg/tests/smoke/testdata/Bob/mistral-large-2402-expected.json +++ /dev/null @@ -1,2700 +0,0 @@ -[ - { - "time": "2024-07-03T10:53:01.406601-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:01.406888-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:02.106674-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:02.107085-04:00", - "callContext": { - "id": "1720018383", - "tool": { - "name": "Mistral La Plateforme Provider", - "description": "Model provider for Mistral models running on La Plateforme", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "mistral la plateforme provider": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/mistral-laplateforme-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "cbf1aeb6db495b9b6223984651d29ac511d2748d" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:03.125117-04:00", - "callContext": { - "id": "1720018383", - "tool": { - "name": "Mistral La Plateforme Provider", - "description": "Model provider for Mistral models running on La Plateforme", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "mistral la plateforme provider": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/mistral-laplateforme-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "cbf1aeb6db495b9b6223984651d29ac511d2748d" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callFinish", - "usage": {}, - "content": "http://127.0.0.1:10244" - }, - { - "time": "2024-07-03T10:53:03.125375-04:00", - "type": "runFinish", - "usage": {} - }, - { - "time": "2024-07-03T10:53:03.12547-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018384", - "usage": {}, - "chatRequest": { - "model": "mistral-large-2402", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-03T10:53:03.126002-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018384", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-03T10:53:03.438634-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018384", - "usage": {} - }, - { - "time": "2024-07-03T10:53:03.917633-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018384", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-03T10:53:03.9181-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018384", - "usage": { - "promptTokens": 188, - "completionTokens": 23, - "totalTokens": 211 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "IePX3uH5y", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 188, - "completionTokens": 23, - "totalTokens": 211 - } - } - }, - { - "time": "2024-07-03T10:53:03.918447-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolSubCalls": { - "IePX3uH5y": { - "toolID": "testdata/Bob/test.gpt:bob", - "input": "{\"question\": \"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-07-03T10:53:03.918585-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-03T10:53:04.089188-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callChat", - "chatCompletionId": "1720018385", - "usage": {}, - "chatRequest": { - "model": "mistral-large-2402", - "messages": [ - { - "role": "system", - "content": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"" - }, - { - "role": "user", - "content": "{\"question\": \"how are you doing\"}" - } - ], - "temperature": 0 - } - }, - { - "time": "2024-07-03T10:53:04.089548-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-03T10:53:04.287287-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {} - }, - { - "time": "2024-07-03T10:53:04.287688-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-07-03T10:53:04.302879-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for" - }, - { - "time": "2024-07-03T10:53:04.323886-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-07-03T10:53:04.345227-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"" - }, - { - "time": "2024-07-03T10:53:04.364182-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how" - }, - { - "time": "2024-07-03T10:53:04.387098-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are" - }, - { - "time": "2024-07-03T10:53:04.405872-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you" - }, - { - "time": "2024-07-03T10:53:04.427749-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing" - }, - { - "time": "2024-07-03T10:53:04.448563-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\"," - }, - { - "time": "2024-07-03T10:53:04.468026-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I" - }, - { - "time": "2024-07-03T10:53:04.490606-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'" - }, - { - "time": "2024-07-03T10:53:04.511171-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm" - }, - { - "time": "2024-07-03T10:53:04.531235-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing" - }, - { - "time": "2024-07-03T10:53:04.553855-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great" - }, - { - "time": "2024-07-03T10:53:04.574503-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow" - }, - { - "time": "2024-07-03T10:53:04.598055-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly" - }, - { - "time": "2024-07-03T10:53:04.613412-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI" - }, - { - "time": "2024-07-03T10:53:04.635897-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-07-03T10:53:04.656116-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-07-03T10:53:04.680962-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callProgress", - "chatCompletionId": "1720018385", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-07-03T10:53:04.681447-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callChat", - "chatCompletionId": "1720018385", - "usage": { - "promptTokens": 143, - "completionTokens": 19, - "totalTokens": 162 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 143, - "completionTokens": 19, - "totalTokens": 162 - } - } - }, - { - "time": "2024-07-03T10:53:04.681598-04:00", - "callContext": { - "id": "IePX3uH5y", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "When asked how I am doing, respond with exactly \"Thanks for asking \"${question}\", I'm doing great fellow friendly AI tool!\"", - "id": "testdata/Bob/test.gpt:bob", - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 6 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018382" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-07-03T10:53:04.681725-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-07-03T10:53:04.842182-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018386", - "usage": {}, - "chatRequest": { - "model": "mistral-large-2402", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "IePX3uH5y", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking \"how are you doing\", I'm doing great fellow friendly AI tool!", - "name": "bob", - "tool_call_id": "IePX3uH5y" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-03T10:53:04.842685-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-03T10:53:05.384131-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {} - }, - { - "time": "2024-07-03T10:53:05.384657-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob" - }, - { - "time": "2024-07-03T10:53:05.404612-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said" - }, - { - "time": "2024-07-03T10:53:05.430068-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said," - }, - { - "time": "2024-07-03T10:53:05.452982-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"" - }, - { - "time": "2024-07-03T10:53:05.501525-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for" - }, - { - "time": "2024-07-03T10:53:05.50179-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for" - }, - { - "time": "2024-07-03T10:53:05.532152-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking" - }, - { - "time": "2024-07-03T10:53:05.553295-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking '" - }, - { - "time": "2024-07-03T10:53:05.576012-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how" - }, - { - "time": "2024-07-03T10:53:05.602885-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are" - }, - { - "time": "2024-07-03T10:53:05.624751-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you" - }, - { - "time": "2024-07-03T10:53:05.649543-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing" - }, - { - "time": "2024-07-03T10:53:05.674199-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing'," - }, - { - "time": "2024-07-03T10:53:05.697398-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I" - }, - { - "time": "2024-07-03T10:53:05.725234-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'" - }, - { - "time": "2024-07-03T10:53:05.747687-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm" - }, - { - "time": "2024-07-03T10:53:05.773761-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing" - }, - { - "time": "2024-07-03T10:53:05.798352-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great" - }, - { - "time": "2024-07-03T10:53:05.823105-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow" - }, - { - "time": "2024-07-03T10:53:05.846373-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly" - }, - { - "time": "2024-07-03T10:53:05.871647-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI" - }, - { - "time": "2024-07-03T10:53:05.895603-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-07-03T10:53:05.919754-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:05.956244-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018386", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:05.956647-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018386", - "usage": { - "promptTokens": 246, - "completionTokens": 23, - "totalTokens": 269 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI tool!\"" - } - ], - "usage": { - "promptTokens": 246, - "completionTokens": 23, - "totalTokens": 269 - } - } - }, - { - "time": "2024-07-03T10:53:05.956695-04:00", - "callContext": { - "id": "1720018382", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/Bob/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/Bob/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/Bob/test.gpt:", - "bob": "testdata/Bob/test.gpt:bob" - }, - "source": { - "location": "testdata/Bob/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/Bob" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Bob said, \"Thanks for asking 'how are you doing', I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:05.956743-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/Bob/test.gpt b/pkg/tests/smoke/testdata/Bob/test.gpt index 20f533e2..535790df 100644 --- a/pkg/tests/smoke/testdata/Bob/test.gpt +++ b/pkg/tests/smoke/testdata/Bob/test.gpt @@ -1,10 +1,10 @@ tools: bob -Ask Bob "how are you doing" and repeat his reply exactly. +Ask Bob "how are you doing" and repeat the response text exactly as given without saying anything else. --- name: bob description: I'm Bob, a friendly guy. args: question: The question to ask Bob. -When asked how I am doing, respond with exactly "Thanks for asking "${QUESTION}", I'm doing great fellow friendly AI tool!" +When asked how I am doing, respond with the following exactly: "Thanks for asking ${QUESTION}! I'm doing great fellow friendly AI tool!" with ${QUESTION} replaced with the question text as given. diff --git a/pkg/tests/smoke/testdata/BobAsShell/claude-3-5-sonnet-20240620-expected.json b/pkg/tests/smoke/testdata/BobAsShell/claude-3-5-sonnet-20240620-expected.json deleted file mode 100644 index 4f3dd9d7..00000000 --- a/pkg/tests/smoke/testdata/BobAsShell/claude-3-5-sonnet-20240620-expected.json +++ /dev/null @@ -1,878 +0,0 @@ -[ - { - "time": "2024-07-02T19:39:48.881112-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:48.881306-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:49.304999-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:49.305331-04:00", - "callContext": { - "id": "1719963590", - "tool": { - "name": "Anthropic Claude3 Model Provider", - "description": "Model provider for Anthropic hosted Claude3 models", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-02T19:39:50.324048-04:00", - "callContext": { - "id": "1719963590", - "tool": { - "name": "Anthropic Claude3 Model Provider", - "description": "Model provider for Anthropic hosted Claude3 models", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt:Anthropic Claude3 Model Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/6b5a88075b1e4501e845f4dab5be16ea8739aa4c" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callFinish", - "usage": {}, - "content": "http://127.0.0.1:10585" - }, - { - "time": "2024-07-02T19:39:50.324287-04:00", - "type": "runFinish", - "usage": {} - }, - { - "time": "2024-07-02T19:39:50.324366-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963591", - "usage": {}, - "chatRequest": { - "model": "claude-3-5-sonnet-20240620", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-02T19:39:50.324921-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963591", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-02T19:39:51.941234-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963591", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-02T19:39:51.941444-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963591", - "usage": {}, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - } - ], - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:51.941523-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolSubCalls": { - "toolu_01SHRzoGuUEQtwBp2ktaqu7P": { - "toolID": "testdata/BobAsShell/test.gpt:bob", - "input": "{\"question\": \"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-07-02T19:39:51.941567-04:00", - "callContext": { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963589", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-02T19:39:51.942241-04:00", - "callContext": { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963589", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1719963592", - "usage": {}, - "chatRequest": { - "model": "", - "messages": null - } - }, - { - "time": "2024-07-02T19:39:51.945596-04:00", - "callContext": { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963589", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callProgress", - "chatCompletionId": "1719963592", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-07-02T19:39:51.945769-04:00", - "callContext": { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963589", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1719963592", - "usage": {}, - "chatResponse": { - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:51.945833-04:00", - "callContext": { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1719963589", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-07-02T19:39:51.945871-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-07-02T19:39:52.112712-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963593", - "usage": {}, - "chatRequest": { - "model": "claude-3-5-sonnet-20240620", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n", - "name": "bob", - "tool_call_id": "toolu_01SHRzoGuUEQtwBp2ktaqu7P" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-02T19:39:52.11309-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963593", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-02T19:39:53.567604-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1719963593", - "usage": {}, - "content": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - }, - { - "time": "2024-07-02T19:39:53.568556-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1719963593", - "usage": {}, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - } - ], - "usage": {} - } - }, - { - "time": "2024-07-02T19:39:53.568602-04:00", - "callContext": { - "id": "1719963589", - "tool": { - "modelName": "claude-3-5-sonnet-20240620 from github.com/gptscript-ai/claude3-anthropic-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Bob's reply to the question \"how are you doing\" is:\n\n\"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"\n\nI have repeated his reply exactly as requested." - }, - { - "time": "2024-07-02T19:39:53.568622-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/BobAsShell/claude-3-7-sonnet-20250219-expected.json b/pkg/tests/smoke/testdata/BobAsShell/claude-3-7-sonnet-20250219-expected.json new file mode 100644 index 00000000..15d59a1f --- /dev/null +++ b/pkg/tests/smoke/testdata/BobAsShell/claude-3-7-sonnet-20250219-expected.json @@ -0,0 +1,601 @@ +[ + { + "time": "2024-10-14T17:38:39.518668-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:39.519079-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:40.155982-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:40.156405-04:00", + "callContext": { + "id": "1728941921", + "tool": { + "name": "Anthropic Claude3 Model Provider", + "description": "Model provider for Anthropic hosted Claude3 models", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "modelProvider": true, + "internalPrompt": null, + "credentials": [ + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" + ], + "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", + "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider", + "toolMapping": { + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ + { + "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", + "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/de2fada1c51a1dbb5c3e9ef268ea6740d1b52f80/tool.gpt:token" + } + ] + }, + "localTools": { + "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider" + }, + "source": { + "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt", + "lineNo": 1, + "repo": { + "VCS": "git", + "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", + "Path": "/", + "Name": "tool.gpt", + "Revision": "ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + } + }, + "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + }, + "currentAgent": {}, + "inputContext": null, + "toolCategory": "provider", + "displayText": "Running sys.daemon" + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:41.173004-04:00", + "callContext": { + "id": "1728941921", + "tool": { + "name": "Anthropic Claude3 Model Provider", + "description": "Model provider for Anthropic hosted Claude3 models", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "modelProvider": true, + "internalPrompt": null, + "credentials": [ + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env" + ], + "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", + "id": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider", + "toolMapping": { + "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env": [ + { + "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/claude3-anthropic-provider/credential with \"Please enter your Anthropic API Key\" as message and token as field and \"ANTHROPIC_API_KEY\" as env", + "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/de2fada1c51a1dbb5c3e9ef268ea6740d1b52f80/tool.gpt:token" + } + ] + }, + "localTools": { + "anthropic claude3 model provider": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt:Anthropic Claude3 Model Provider" + }, + "source": { + "location": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344/tool.gpt", + "lineNo": 1, + "repo": { + "VCS": "git", + "Root": "https://github.com/gptscript-ai/claude3-anthropic-provider.git", + "Path": "/", + "Name": "tool.gpt", + "Revision": "ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + } + }, + "workingDir": "https://raw.githubusercontent.com/gptscript-ai/claude3-anthropic-provider/ee5c02a9aeca5a1cbffcf569751e37432bfe0344" + }, + "currentAgent": {}, + "inputContext": null, + "toolCategory": "provider", + "displayText": "Running sys.daemon" + }, + "type": "callFinish", + "usage": {}, + "content": "http://127.0.0.1:10787" + }, + { + "time": "2024-10-14T17:38:41.173175-04:00", + "type": "runFinish", + "usage": {} + }, + { + "time": "2024-10-14T17:38:41.173247-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941922", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:43.937061-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941922", + "usage": {}, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "toolu_01PQYSGxbwRLw8XuUUkgKvbe", + "function": { + "name": "bob", + "arguments": "{\"question\": \"how are you doing\"}" + } + } + } + ], + "usage": {} + } + }, + { + "time": "2024-10-14T17:38:43.937155-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "toolu_01PQYSGxbwRLw8XuUUkgKvbe": { + "toolID": "testdata/BobAsShell/test.gpt:bob", + "input": "{\"question\": \"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T17:38:43.937193-04:00", + "callContext": { + "id": "toolu_01PQYSGxbwRLw8XuUUkgKvbe", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941920", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\": \"how are you doing\"}" + }, + { + "time": "2024-10-14T17:38:43.938264-04:00", + "callContext": { + "id": "toolu_01PQYSGxbwRLw8XuUUkgKvbe", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941920", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941923", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:43.943625-04:00", + "callContext": { + "id": "toolu_01PQYSGxbwRLw8XuUUkgKvbe", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941920", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941923", + "usage": {}, + "chatResponse": { + "usage": {} + } + }, + { + "time": "2024-10-14T17:38:43.943703-04:00", + "callContext": { + "id": "toolu_01PQYSGxbwRLw8XuUUkgKvbe", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941920", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" + }, + { + "time": "2024-10-14T17:38:43.943766-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T17:38:44.494388-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941924", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:45.659797-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941924", + "usage": {}, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + } + ], + "usage": {} + } + }, + { + "time": "2024-10-14T17:38:45.659891-04:00", + "callContext": { + "id": "1728941920", + "tool": { + "modelName": "claude-3-7-sonnet-20250219 from github.com/gptscript-ai/claude3-anthropic-provider", + "internalPrompt": null, + "tools": ["bob"], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T17:38:45.659921-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/BobAsShell/gpt-4-turbo-2024-04-09-expected.json b/pkg/tests/smoke/testdata/BobAsShell/gpt-4-turbo-2024-04-09-expected.json deleted file mode 100644 index 5b2409f6..00000000 --- a/pkg/tests/smoke/testdata/BobAsShell/gpt-4-turbo-2024-04-09-expected.json +++ /dev/null @@ -1,1549 +0,0 @@ -[ - { - "time": "2024-06-20T17:08:30.778302-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-06-20T17:08:30.778582-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-06-20T17:08:30.981266-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917712", - "usage": {}, - "chatRequest": { - "model": "gpt-4-turbo-2024-04-09", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T17:08:30.981391-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T17:08:32.232987-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T17:08:32.233265-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T17:08:32.344744-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T17:08:32.344882-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T17:08:32.361676-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T17:08:32.361793-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T17:08:32.440498-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing" - }, - { - "time": "2024-06-20T17:08:32.440743-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:32.440798-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:32.440836-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:32.440873-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917712", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:32.441115-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917712", - "usage": { - "promptTokens": 142, - "completionTokens": 17, - "totalTokens": 159 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 142, - "completionTokens": 17, - "totalTokens": 159 - } - } - }, - { - "time": "2024-06-20T17:08:32.441462-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "toolSubCalls": { - "call_slFgd2P2lMxXQoyrPbm2YsrQ": { - "toolID": "testdata/BobAsShell/test.gpt:bob", - "input": "{\"question\":\"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-06-20T17:08:32.441542-04:00", - "callContext": { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917711", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T17:08:32.442736-04:00", - "callContext": { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917711", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1718917713", - "usage": {}, - "chatRequest": { - "model": "", - "messages": null - } - }, - { - "time": "2024-06-20T17:08:32.448288-04:00", - "callContext": { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917711", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callProgress", - "chatCompletionId": "1718917713", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-06-20T17:08:32.448728-04:00", - "callContext": { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917711", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1718917713", - "usage": {}, - "chatResponse": { - "usage": {} - } - }, - { - "time": "2024-06-20T17:08:32.448906-04:00", - "callContext": { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917711", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-06-20T17:08:32.448977-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-06-20T17:08:32.624086-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917714", - "usage": {}, - "chatRequest": { - "model": "gpt-4-turbo-2024-04-09", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_slFgd2P2lMxXQoyrPbm2YsrQ", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n", - "name": "bob", - "tool_call_id": "call_slFgd2P2lMxXQoyrPbm2YsrQ" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T17:08:32.624367-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T17:08:33.020025-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I" - }, - { - "time": "2024-06-20T17:08:33.020187-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I" - }, - { - "time": "2024-06-20T17:08:33.09047-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing" - }, - { - "time": "2024-06-20T17:08:33.090722-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing" - }, - { - "time": "2024-06-20T17:08:33.150983-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow" - }, - { - "time": "2024-06-20T17:08:33.151128-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow" - }, - { - "time": "2024-06-20T17:08:33.26424-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI" - }, - { - "time": "2024-06-20T17:08:33.264352-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T17:08:33.264393-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T17:08:33.264427-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:33.264492-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:33.264575-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917714", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:33.264897-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917714", - "usage": { - "promptTokens": 183, - "completionTokens": 10, - "totalTokens": 193 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 183, - "completionTokens": 10, - "totalTokens": 193 - } - } - }, - { - "time": "2024-06-20T17:08:33.264985-04:00", - "callContext": { - "id": "1718917711", - "tool": { - "modelName": "gpt-4-turbo-2024-04-09", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T17:08:33.265021-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-05-13-expected.json b/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-05-13-expected.json deleted file mode 100644 index f61edd7d..00000000 --- a/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-05-13-expected.json +++ /dev/null @@ -1,1808 +0,0 @@ -[ - { - "time": "2024-06-20T16:58:14.093283-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-06-20T16:58:14.093568-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-06-20T16:58:14.31069-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917096", - "usage": {}, - "chatRequest": { - "model": "gpt-4o-2024-05-13", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T16:58:14.311071-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T16:58:14.807492-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T16:58:14.807779-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"" - }, - { - "time": "2024-06-20T16:58:14.832551-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T16:58:14.832684-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"" - }, - { - "time": "2024-06-20T16:58:14.865368-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T16:58:14.865484-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are" - }, - { - "time": "2024-06-20T16:58:14.899511-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing" - }, - { - "time": "2024-06-20T16:58:14.899668-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing" - }, - { - "time": "2024-06-20T16:58:14.900883-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:14.900938-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:14.900969-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917096", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:14.901222-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917096", - "usage": { - "promptTokens": 138, - "completionTokens": 17, - "totalTokens": 155 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 138, - "completionTokens": 17, - "totalTokens": 155 - } - } - }, - { - "time": "2024-06-20T16:58:14.901521-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "toolSubCalls": { - "call_PGLxooO6eBPt3eSEBCMkuWYN": { - "toolID": "testdata/BobAsShell/test.gpt:bob", - "input": "{\"question\":\"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-06-20T16:58:14.901599-04:00", - "callContext": { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917095", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\":\"how are you doing\"}" - }, - { - "time": "2024-06-20T16:58:14.90268-04:00", - "callContext": { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917095", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1718917097", - "usage": {}, - "chatRequest": { - "model": "", - "messages": null - } - }, - { - "time": "2024-06-20T16:58:14.908538-04:00", - "callContext": { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917095", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callProgress", - "chatCompletionId": "1718917097", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-06-20T16:58:14.908991-04:00", - "callContext": { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917095", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1718917097", - "usage": {}, - "chatResponse": { - "usage": {} - } - }, - { - "time": "2024-06-20T16:58:14.909126-04:00", - "callContext": { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null, - "toolName": "bob", - "parentID": "1718917095", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-06-20T16:58:14.909293-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-06-20T16:58:15.10962-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917098", - "usage": {}, - "chatRequest": { - "model": "gpt-4o-2024-05-13", - "messages": [ - { - "role": "system", - "content": "\nYou are task oriented system.\nYou receive input from a user, process the input from the given instructions, and then output the result.\nYour objective is to provide consistent and correct results.\nYou do not need to explain the steps taken, only provide the result to the given instructions.\nYou are referred to as a tool.\nYou don't move to the next step until you have a result.\n\nAsk Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "call_PGLxooO6eBPt3eSEBCMkuWYN", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\":\"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n", - "name": "bob", - "tool_call_id": "call_PGLxooO6eBPt3eSEBCMkuWYN" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-06-20T16:58:15.110087-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-06-20T16:58:15.629792-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T16:58:15.629968-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks" - }, - { - "time": "2024-06-20T16:58:15.749206-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for" - }, - { - "time": "2024-06-20T16:58:15.749324-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking" - }, - { - "time": "2024-06-20T16:58:15.780062-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are" - }, - { - "time": "2024-06-20T16:58:15.780171-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you" - }, - { - "time": "2024-06-20T16:58:15.780293-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing" - }, - { - "time": "2024-06-20T16:58:15.780335-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing" - }, - { - "time": "2024-06-20T16:58:15.780406-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm" - }, - { - "time": "2024-06-20T16:58:15.780445-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm" - }, - { - "time": "2024-06-20T16:58:15.780477-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing" - }, - { - "time": "2024-06-20T16:58:15.780511-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great" - }, - { - "time": "2024-06-20T16:58:15.816742-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T16:58:15.816889-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly" - }, - { - "time": "2024-06-20T16:58:15.859699-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-06-20T16:58:15.859764-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:15.859784-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:15.859841-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:15.85986-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1718917098", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:15.860819-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1718917098", - "usage": { - "promptTokens": 178, - "completionTokens": 17, - "totalTokens": 195 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - } - ], - "usage": { - "promptTokens": 178, - "completionTokens": 17, - "totalTokens": 195 - } - } - }, - { - "time": "2024-06-20T16:58:15.860872-04:00", - "callContext": { - "id": "1718917095", - "tool": { - "modelName": "gpt-4o-2024-05-13", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" - }, - { - "time": "2024-06-20T16:58:15.860919-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-08-06-expected.json b/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-08-06-expected.json new file mode 100644 index 00000000..91b6a636 --- /dev/null +++ b/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-2024-08-06-expected.json @@ -0,0 +1,528 @@ +[ + { + "time": "2024-10-14T17:38:25.173529-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:25.174285-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T17:38:25.174351-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941907", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:26.165696-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941907", + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "call_95p8Knb4mdiEgxt5iXxnxOKC", + "function": { + "name": "bob", + "arguments": "{\"question\":\"how are you doing\"}" + } + } + } + ], + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + } + } + }, + { + "time": "2024-10-14T17:38:26.165858-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "call_95p8Knb4mdiEgxt5iXxnxOKC": { + "toolID": "testdata/BobAsShell/test.gpt:bob", + "input": "{\"question\":\"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T17:38:26.165964-04:00", + "callContext": { + "id": "call_95p8Knb4mdiEgxt5iXxnxOKC", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941906", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\":\"how are you doing\"}" + }, + { + "time": "2024-10-14T17:38:26.167235-04:00", + "callContext": { + "id": "call_95p8Knb4mdiEgxt5iXxnxOKC", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941906", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941908", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:26.178131-04:00", + "callContext": { + "id": "call_95p8Knb4mdiEgxt5iXxnxOKC", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941906", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941908", + "usage": {}, + "chatResponse": { + "usage": {} + } + }, + { + "time": "2024-10-14T17:38:26.178199-04:00", + "callContext": { + "id": "call_95p8Knb4mdiEgxt5iXxnxOKC", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941906", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" + }, + { + "time": "2024-10-14T17:38:26.178356-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T17:38:26.178539-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941909", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:38:27.001877-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941909", + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + } + } + }, + { + "time": "2024-10-14T17:38:27.001903-04:00", + "callContext": { + "id": "1728941906", + "tool": { + "modelName": "gpt-4o-2024-08-06", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T17:38:27.001932-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-mini-2024-07-18-expected.json b/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-mini-2024-07-18-expected.json new file mode 100644 index 00000000..bdfee87d --- /dev/null +++ b/pkg/tests/smoke/testdata/BobAsShell/gpt-4o-mini-2024-07-18-expected.json @@ -0,0 +1,528 @@ +[ + { + "time": "2024-10-14T17:37:54.379122-04:00", + "type": "runStart", + "usage": {} + }, + { + "time": "2024-10-14T17:37:54.379631-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callStart", + "usage": {} + }, + { + "time": "2024-10-14T17:37:54.379682-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941876", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:37:55.230509-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941876", + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "toolCall": { + "index": 0, + "id": "call_FInUoOxKSR90EOxzIHXivvSX", + "function": { + "name": "bob", + "arguments": "{\"question\":\"how are you doing\"}" + } + } + } + ], + "usage": { + "promptTokens": 145, + "completionTokens": 17, + "totalTokens": 162 + } + } + }, + { + "time": "2024-10-14T17:37:55.23069-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolSubCalls": { + "call_FInUoOxKSR90EOxzIHXivvSX": { + "toolID": "testdata/BobAsShell/test.gpt:bob", + "input": "{\"question\":\"how are you doing\"}" + } + }, + "type": "callSubCalls", + "usage": {} + }, + { + "time": "2024-10-14T17:37:55.230816-04:00", + "callContext": { + "id": "call_FInUoOxKSR90EOxzIHXivvSX", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941875", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callStart", + "usage": {}, + "content": "{\"question\":\"how are you doing\"}" + }, + { + "time": "2024-10-14T17:37:55.231913-04:00", + "callContext": { + "id": "call_FInUoOxKSR90EOxzIHXivvSX", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941875", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941877", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:37:55.245261-04:00", + "callContext": { + "id": "call_FInUoOxKSR90EOxzIHXivvSX", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941875", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callChat", + "chatCompletionId": "1728941877", + "usage": {}, + "chatResponse": { + "usage": {} + } + }, + { + "time": "2024-10-14T17:37:55.245348-04:00", + "callContext": { + "id": "call_FInUoOxKSR90EOxzIHXivvSX", + "tool": { + "name": "bob", + "description": "I'm Bob, a friendly guy.", + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "arguments": { + "properties": { + "question": { + "description": "The question to ask Bob.", + "type": "string" + } + }, + "type": "object" + }, + "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${QUESTION}, I'm doing great fellow friendly AI tool!\"", + "id": "testdata/BobAsShell/test.gpt:bob", + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 6 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null, + "toolName": "bob", + "parentID": "1728941875", + "displayText": "Running bob from testdata/BobAsShell/test.gpt" + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" + }, + { + "time": "2024-10-14T17:37:55.245528-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "toolResults": 1, + "type": "callContinue", + "usage": {} + }, + { + "time": "2024-10-14T17:37:55.245751-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941878", + "usage": {}, + "chatRequest": { + "model": "", + "messages": null + } + }, + { + "time": "2024-10-14T17:37:56.345692-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callChat", + "chatCompletionId": "1728941878", + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + }, + "chatResponse": { + "role": "assistant", + "content": [ + { + "text": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + } + ], + "usage": { + "promptTokens": 185, + "completionTokens": 17, + "totalTokens": 202 + } + } + }, + { + "time": "2024-10-14T17:37:56.345742-04:00", + "callContext": { + "id": "1728941875", + "tool": { + "modelName": "gpt-4o-mini-2024-07-18", + "internalPrompt": null, + "tools": [ + "bob" + ], + "instructions": "Ask Bob \"how are you doing\" and repeat the response text exactly as given without saying anything else.", + "id": "testdata/BobAsShell/test.gpt:", + "toolMapping": { + "bob": [ + { + "reference": "bob", + "toolID": "testdata/BobAsShell/test.gpt:bob" + } + ] + }, + "localTools": { + "": "testdata/BobAsShell/test.gpt:", + "bob": "testdata/BobAsShell/test.gpt:bob" + }, + "source": { + "location": "testdata/BobAsShell/test.gpt", + "lineNo": 1 + }, + "workingDir": "testdata/BobAsShell" + }, + "currentAgent": {}, + "inputContext": null + }, + "type": "callFinish", + "usage": {}, + "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!" + }, + { + "time": "2024-10-14T17:37:56.345803-04:00", + "type": "runFinish", + "usage": {} + } +] diff --git a/pkg/tests/smoke/testdata/BobAsShell/mistral-large-2402-expected.json b/pkg/tests/smoke/testdata/BobAsShell/mistral-large-2402-expected.json deleted file mode 100644 index 43df5fa7..00000000 --- a/pkg/tests/smoke/testdata/BobAsShell/mistral-large-2402-expected.json +++ /dev/null @@ -1,1804 +0,0 @@ -[ - { - "time": "2024-07-03T10:53:05.993864-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:05.99419-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:06.366435-04:00", - "type": "runStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:06.366952-04:00", - "callContext": { - "id": "1720018387", - "tool": { - "name": "Mistral La Plateforme Provider", - "description": "Model provider for Mistral models running on La Plateforme", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "mistral la plateforme provider": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/mistral-laplateforme-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "cbf1aeb6db495b9b6223984651d29ac511d2748d" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callStart", - "usage": {} - }, - { - "time": "2024-07-03T10:53:07.383203-04:00", - "callContext": { - "id": "1720018387", - "tool": { - "name": "Mistral La Plateforme Provider", - "description": "Model provider for Mistral models running on La Plateforme", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "modelProvider": true, - "internalPrompt": null, - "credentials": [ - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env" - ], - "instructions": "#!sys.daemon /usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py", - "id": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider", - "toolMapping": { - "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env": [ - { - "reference": "github.com/gptscript-ai/credential as github.com/gptscript-ai/mistral-laplateforme-provider/credential with \"Please enter your Mistral La Plateforme API Key\" as message and token as field and \"MISTRAL_API_KEY\" as env", - "toolID": "https://raw.githubusercontent.com/gptscript-ai/credential/651dfad6e7cf3a385ef408afa93ce522c10f8508/tool.gpt:token" - } - ] - }, - "localTools": { - "mistral la plateforme provider": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt:Mistral La Plateforme Provider" - }, - "source": { - "location": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d/tool.gpt", - "lineNo": 1, - "repo": { - "VCS": "git", - "Root": "https://github.com/gptscript-ai/mistral-laplateforme-provider.git", - "Path": "/", - "Name": "tool.gpt", - "Revision": "cbf1aeb6db495b9b6223984651d29ac511d2748d" - } - }, - "workingDir": "https://raw.githubusercontent.com/gptscript-ai/mistral-laplateforme-provider/cbf1aeb6db495b9b6223984651d29ac511d2748d" - }, - "currentAgent": {}, - "inputContext": null, - "toolCategory": "provider", - "displayText": "Running sys.daemon" - }, - "type": "callFinish", - "usage": {}, - "content": "http://127.0.0.1:10798" - }, - { - "time": "2024-07-03T10:53:07.383553-04:00", - "type": "runFinish", - "usage": {} - }, - { - "time": "2024-07-03T10:53:07.383621-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018388", - "usage": {}, - "chatRequest": { - "model": "mistral-large-2402", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-03T10:53:07.384109-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018388", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-03T10:53:07.670442-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018388", - "usage": {} - }, - { - "time": "2024-07-03T10:53:08.283965-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018388", - "usage": {}, - "content": "\u003ctool call\u003e bob -\u003e {\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-03T10:53:08.284275-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018388", - "usage": { - "promptTokens": 188, - "completionTokens": 23, - "totalTokens": 211 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "toolCall": { - "index": 0, - "id": "K9FVJPqm6", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - } - ], - "usage": { - "promptTokens": 188, - "completionTokens": 23, - "totalTokens": 211 - } - } - }, - { - "time": "2024-07-03T10:53:08.285881-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolSubCalls": { - "K9FVJPqm6": { - "toolID": "testdata/BobAsShell/test.gpt:bob", - "input": "{\"question\": \"how are you doing\"}" - } - }, - "type": "callSubCalls", - "usage": {} - }, - { - "time": "2024-07-03T10:53:08.286454-04:00", - "callContext": { - "id": "K9FVJPqm6", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018386", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callStart", - "usage": {}, - "content": "{\"question\": \"how are you doing\"}" - }, - { - "time": "2024-07-03T10:53:08.287602-04:00", - "callContext": { - "id": "K9FVJPqm6", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018386", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1720018389", - "usage": {}, - "chatRequest": { - "model": "", - "messages": null - } - }, - { - "time": "2024-07-03T10:53:08.295318-04:00", - "callContext": { - "id": "K9FVJPqm6", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018386", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callProgress", - "chatCompletionId": "1720018389", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-07-03T10:53:08.295753-04:00", - "callContext": { - "id": "K9FVJPqm6", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018386", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callChat", - "chatCompletionId": "1720018389", - "usage": {}, - "chatResponse": { - "usage": {} - } - }, - { - "time": "2024-07-03T10:53:08.29586-04:00", - "callContext": { - "id": "K9FVJPqm6", - "tool": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "arguments": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - }, - "instructions": "#!/bin/bash\n\necho \"Thanks for asking ${question}, I'm doing great fellow friendly AI tool!\"", - "id": "testdata/BobAsShell/test.gpt:bob", - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 7 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null, - "toolName": "bob", - "parentID": "1720018386", - "displayText": "Running bob from testdata/BobAsShell/test.gpt" - }, - "type": "callFinish", - "usage": {}, - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n" - }, - { - "time": "2024-07-03T10:53:08.295955-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "toolResults": 1, - "type": "callContinue", - "usage": {} - }, - { - "time": "2024-07-03T10:53:08.467884-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018390", - "usage": {}, - "chatRequest": { - "model": "mistral-large-2402", - "messages": [ - { - "role": "system", - "content": "Ask Bob \"how are you doing\" and repeat his reply exactly." - }, - { - "role": "assistant", - "content": "", - "tool_calls": [ - { - "id": "K9FVJPqm6", - "type": "function", - "function": { - "name": "bob", - "arguments": "{\"question\": \"how are you doing\"}" - } - } - ] - }, - { - "role": "tool", - "content": "Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\n", - "name": "bob", - "tool_call_id": "K9FVJPqm6" - } - ], - "temperature": 0, - "tools": [ - { - "type": "function", - "function": { - "name": "bob", - "description": "I'm Bob, a friendly guy.", - "parameters": { - "properties": { - "question": { - "description": "The question to ask Bob.", - "type": "string" - } - }, - "type": "object" - } - } - } - ] - } - }, - { - "time": "2024-07-03T10:53:08.468218-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Waiting for model response..." - }, - { - "time": "2024-07-03T10:53:08.755588-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {} - }, - { - "time": "2024-07-03T10:53:08.756052-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob" - }, - { - "time": "2024-07-03T10:53:08.792872-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said" - }, - { - "time": "2024-07-03T10:53:08.843651-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said," - }, - { - "time": "2024-07-03T10:53:08.890513-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"" - }, - { - "time": "2024-07-03T10:53:08.940592-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks" - }, - { - "time": "2024-07-03T10:53:08.979075-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for" - }, - { - "time": "2024-07-03T10:53:09.026193-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking" - }, - { - "time": "2024-07-03T10:53:09.082478-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how" - }, - { - "time": "2024-07-03T10:53:09.120629-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are" - }, - { - "time": "2024-07-03T10:53:09.169561-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you" - }, - { - "time": "2024-07-03T10:53:09.216601-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing" - }, - { - "time": "2024-07-03T10:53:09.261113-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing," - }, - { - "time": "2024-07-03T10:53:09.306429-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I" - }, - { - "time": "2024-07-03T10:53:09.354951-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'" - }, - { - "time": "2024-07-03T10:53:09.401888-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm" - }, - { - "time": "2024-07-03T10:53:09.448467-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing" - }, - { - "time": "2024-07-03T10:53:09.493586-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great" - }, - { - "time": "2024-07-03T10:53:09.537745-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow" - }, - { - "time": "2024-07-03T10:53:09.585266-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly" - }, - { - "time": "2024-07-03T10:53:09.63097-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI" - }, - { - "time": "2024-07-03T10:53:09.678117-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool" - }, - { - "time": "2024-07-03T10:53:09.726398-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:09.773449-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callProgress", - "chatCompletionId": "1720018390", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:09.774342-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callChat", - "chatCompletionId": "1720018390", - "usage": { - "promptTokens": 247, - "completionTokens": 22, - "totalTokens": 269 - }, - "chatResponse": { - "role": "assistant", - "content": [ - { - "text": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"" - } - ], - "usage": { - "promptTokens": 247, - "completionTokens": 22, - "totalTokens": 269 - } - } - }, - { - "time": "2024-07-03T10:53:09.774431-04:00", - "callContext": { - "id": "1720018386", - "tool": { - "modelName": "mistral-large-2402 from github.com/gptscript-ai/mistral-laplateforme-provider", - "internalPrompt": null, - "tools": [ - "bob" - ], - "instructions": "Ask Bob \"how are you doing\" and repeat his reply exactly.", - "id": "testdata/BobAsShell/test.gpt:", - "toolMapping": { - "bob": [ - { - "reference": "bob", - "toolID": "testdata/BobAsShell/test.gpt:bob" - } - ] - }, - "localTools": { - "": "testdata/BobAsShell/test.gpt:", - "bob": "testdata/BobAsShell/test.gpt:bob" - }, - "source": { - "location": "testdata/BobAsShell/test.gpt", - "lineNo": 1 - }, - "workingDir": "testdata/BobAsShell" - }, - "currentAgent": {}, - "inputContext": null - }, - "type": "callFinish", - "usage": {}, - "content": "Bob said, \"Thanks for asking how are you doing, I'm doing great fellow friendly AI tool!\"" - }, - { - "time": "2024-07-03T10:53:09.774496-04:00", - "type": "runFinish", - "usage": {} - } -] diff --git a/pkg/tests/smoke/testdata/BobAsShell/test.gpt b/pkg/tests/smoke/testdata/BobAsShell/test.gpt index a0edb9c4..6fdc514b 100644 --- a/pkg/tests/smoke/testdata/BobAsShell/test.gpt +++ b/pkg/tests/smoke/testdata/BobAsShell/test.gpt @@ -1,7 +1,6 @@ - tools: bob -Ask Bob "how are you doing" and repeat his reply exactly. +Ask Bob "how are you doing" and repeat the response text exactly as given without saying anything else. --- name: bob diff --git a/pkg/tests/testdata/TestAgentOnly/call1.golden b/pkg/tests/testdata/TestAgentOnly/call1.golden index b63c6fd3..6fadf4ed 100644 --- a/pkg/tests/testdata/TestAgentOnly/call1.golden +++ b/pkg/tests/testdata/TestAgentOnly/call1.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgentOnly/call2.golden b/pkg/tests/testdata/TestAgentOnly/call2.golden index 7f6b155b..909faf53 100644 --- a/pkg/tests/testdata/TestAgentOnly/call2.golden +++ b/pkg/tests/testdata/TestAgentOnly/call2.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent3", "name": "agent3", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -22,13 +22,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgentOnly/step1.golden b/pkg/tests/testdata/TestAgentOnly/step1.golden index 2cda2025..9bf8e319 100644 --- a/pkg/tests/testdata/TestAgentOnly/step1.golden +++ b/pkg/tests/testdata/TestAgentOnly/step1.golden @@ -15,13 +15,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -99,13 +99,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent3", "name": "agent3", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -114,13 +114,13 @@ "toolID": "testdata/TestAgentOnly/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgents/call1.golden b/pkg/tests/testdata/TestAgents/call1.golden index d3c4a86d..be85da0e 100644 --- a/pkg/tests/testdata/TestAgents/call1.golden +++ b/pkg/tests/testdata/TestAgents/call1.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -22,13 +22,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgents/call2.golden b/pkg/tests/testdata/TestAgents/call2.golden index 950ad2ea..b0c301f8 100644 --- a/pkg/tests/testdata/TestAgents/call2.golden +++ b/pkg/tests/testdata/TestAgents/call2.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgents/call3.golden b/pkg/tests/testdata/TestAgents/call3.golden index 5b1638e0..237c6c84 100644 --- a/pkg/tests/testdata/TestAgents/call3.golden +++ b/pkg/tests/testdata/TestAgents/call3.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent3", "name": "agent3", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -22,13 +22,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAgents/step1.golden b/pkg/tests/testdata/TestAgents/step1.golden index 72e01114..d97b6495 100644 --- a/pkg/tests/testdata/TestAgents/step1.golden +++ b/pkg/tests/testdata/TestAgents/step1.golden @@ -15,13 +15,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -30,13 +30,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -110,13 +110,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent2", "name": "agent2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -181,13 +181,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent3", "name": "agent3", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -196,13 +196,13 @@ "toolID": "testdata/TestAgents/test.gpt:agent1", "name": "agent1", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestAsterick/call1.golden b/pkg/tests/testdata/TestAsterick/call1.golden index 3f2fa0b1..d741da5d 100644 --- a/pkg/tests/testdata/TestAsterick/call1.golden +++ b/pkg/tests/testdata/TestAsterick/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestAsterick/other.gpt:afoo", "name": "afoo", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestAsterick/other.gpt:a", "name": "a", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestCase/call1.golden b/pkg/tests/testdata/TestCase/call1.golden index 1e6d76a5..c9bbcbb2 100644 --- a/pkg/tests/testdata/TestCase/call1.golden +++ b/pkg/tests/testdata/TestCase/call1.golden @@ -7,13 +7,13 @@ "name": "Bob", "description": "I'm Bob, a friendly guy.", "parameters": { + "type": "object", "properties": { "question": { - "description": "The question to ask Bob.", - "type": "string" + "type": "string", + "description": "The question to ask Bob." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestCase2/call1.golden b/pkg/tests/testdata/TestCase2/call1.golden index d9b446d0..fc7a5728 100644 --- a/pkg/tests/testdata/TestCase2/call1.golden +++ b/pkg/tests/testdata/TestCase2/call1.golden @@ -7,13 +7,13 @@ "name": "bob", "description": "I'm Bob, a friendly guy.", "parameters": { + "type": "object", "properties": { "question": { - "description": "The question to ask Bob.", - "type": "string" + "type": "string", + "description": "The question to ask Bob." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestContextSubChat/call1.golden b/pkg/tests/testdata/TestContextSubChat/call1.golden index 225401db..fd641ecc 100644 --- a/pkg/tests/testdata/TestContextSubChat/call1.golden +++ b/pkg/tests/testdata/TestContextSubChat/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestContextSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestContextSubChat/call2.golden b/pkg/tests/testdata/TestContextSubChat/call2.golden index a6cf25c6..b5f30991 100644 --- a/pkg/tests/testdata/TestContextSubChat/call2.golden +++ b/pkg/tests/testdata/TestContextSubChat/call2.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call1.golden b/pkg/tests/testdata/TestDualSubChat/call1.golden index 2baf798a..52ab033a 100644 --- a/pkg/tests/testdata/TestDualSubChat/call1.golden +++ b/pkg/tests/testdata/TestDualSubChat/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot2", "name": "chatbot2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call2.golden b/pkg/tests/testdata/TestDualSubChat/call2.golden index a6cf25c6..b5f30991 100644 --- a/pkg/tests/testdata/TestDualSubChat/call2.golden +++ b/pkg/tests/testdata/TestDualSubChat/call2.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call3.golden b/pkg/tests/testdata/TestDualSubChat/call3.golden index ddcc81c9..ca431fc8 100644 --- a/pkg/tests/testdata/TestDualSubChat/call3.golden +++ b/pkg/tests/testdata/TestDualSubChat/call3.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call4.golden b/pkg/tests/testdata/TestDualSubChat/call4.golden index 600e3ba5..580fdb86 100644 --- a/pkg/tests/testdata/TestDualSubChat/call4.golden +++ b/pkg/tests/testdata/TestDualSubChat/call4.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call5.golden b/pkg/tests/testdata/TestDualSubChat/call5.golden index 54823934..de6a4a77 100644 --- a/pkg/tests/testdata/TestDualSubChat/call5.golden +++ b/pkg/tests/testdata/TestDualSubChat/call5.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call6.golden b/pkg/tests/testdata/TestDualSubChat/call6.golden index a9a8a1c4..d3bbb31d 100644 --- a/pkg/tests/testdata/TestDualSubChat/call6.golden +++ b/pkg/tests/testdata/TestDualSubChat/call6.golden @@ -8,13 +8,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/call7.golden b/pkg/tests/testdata/TestDualSubChat/call7.golden index ff19a0e8..de734587 100644 --- a/pkg/tests/testdata/TestDualSubChat/call7.golden +++ b/pkg/tests/testdata/TestDualSubChat/call7.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot2", "name": "chatbot2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/step1.golden b/pkg/tests/testdata/TestDualSubChat/step1.golden index f29dfd60..b866f976 100644 --- a/pkg/tests/testdata/TestDualSubChat/step1.golden +++ b/pkg/tests/testdata/TestDualSubChat/step1.golden @@ -14,13 +14,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -29,13 +29,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot2", "name": "chatbot2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -135,13 +135,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } @@ -200,13 +200,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/step2.golden b/pkg/tests/testdata/TestDualSubChat/step2.golden index 830a8e7c..8876c290 100644 --- a/pkg/tests/testdata/TestDualSubChat/step2.golden +++ b/pkg/tests/testdata/TestDualSubChat/step2.golden @@ -14,13 +14,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -29,13 +29,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot2", "name": "chatbot2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -142,13 +142,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestDualSubChat/step3.golden b/pkg/tests/testdata/TestDualSubChat/step3.golden index 4f3b415a..1876df5b 100644 --- a/pkg/tests/testdata/TestDualSubChat/step3.golden +++ b/pkg/tests/testdata/TestDualSubChat/step3.golden @@ -14,13 +14,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -29,13 +29,13 @@ "toolID": "testdata/TestDualSubChat/test.gpt:chatbot2", "name": "chatbot2", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } @@ -142,13 +142,13 @@ "name": "chatFinish", "description": "Concludes the conversation. This can not be used to ask a question.", "parameters": { + "type": "object", "properties": { "return": { - "description": "The instructed value to return or a summary of the dialog if no value is instructed", - "type": "string" + "type": "string", + "description": "The instructed value to return or a summary of the dialog if no value is instructed" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestExport/call1.golden b/pkg/tests/testdata/TestExport/call1.golden index b700ee55..8b663ff3 100644 --- a/pkg/tests/testdata/TestExport/call1.golden +++ b/pkg/tests/testdata/TestExport/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestExport/parent.gpt:frommain", "name": "frommain", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestExport/sub/child.gpt:transient", "name": "transient", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -36,13 +36,13 @@ "toolID": "testdata/TestExport/parent.gpt:parent-local", "name": "parentLocal", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestExport/call3.golden b/pkg/tests/testdata/TestExport/call3.golden index d2abca0c..181980aa 100644 --- a/pkg/tests/testdata/TestExport/call3.golden +++ b/pkg/tests/testdata/TestExport/call3.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestExport/parent.gpt:frommain", "name": "frommain", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestExport/sub/child.gpt:transient", "name": "transient", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -36,13 +36,13 @@ "toolID": "testdata/TestExport/parent.gpt:parent-local", "name": "parentLocal", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestExportContext/call1.golden b/pkg/tests/testdata/TestExportContext/call1.golden index 0ee8f9fe..7ba20676 100644 --- a/pkg/tests/testdata/TestExportContext/call1.golden +++ b/pkg/tests/testdata/TestExportContext/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestExportContext/test.gpt:subtool", "name": "subtool", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -22,13 +22,13 @@ "name": "sampletool", "description": "sample", "parameters": { + "type": "object", "properties": { "foo": { - "description": "foo description", - "type": "string" + "type": "string", + "description": "foo description" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestFilterArgs/step1.golden b/pkg/tests/testdata/TestFilterArgs/step1.golden new file mode 100644 index 00000000..a6e6599b --- /dev/null +++ b/pkg/tests/testdata/TestFilterArgs/step1.golden @@ -0,0 +1,6 @@ +`{ + "done": true, + "content": "{\"chat\":false,\"continuation\":false,\"notfoo\":\"baz\",\"output\":\"{\\\"chat\\\":false,\\\"continuation\\\":false,\\\"notfoo\\\":\\\"foo\\\",\\\"output\\\":\\\"{\\\\\\\"chat\\\\\\\":false,\\\\\\\"continuation\\\\\\\":false,\\\\\\\"foo\\\\\\\":\\\\\\\"baz\\\\\\\",\\\\\\\"input\\\\\\\":\\\\\\\"{\\\\\\\\\\\\\\\"foo\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"baz\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"input\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"foo\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"baz\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"start\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\": true}\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"notfoo\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"baz\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"start\\\\\\\\\\\\\\\":true}\\\\\\\\n\\\\\\\",\\\\\\\"notfoo\\\\\\\":\\\\\\\"foo\\\\\\\",\\\\\\\"output\\\\\\\":\\\\\\\"baz\\\\\\\\n\\\\\\\",\\\\\\\"start\\\\\\\":true}\\\\n\\\"}\\n\"}\n", + "toolID": "", + "state": null +}` diff --git a/pkg/tests/testdata/TestMCPLoad/call1-resp.golden b/pkg/tests/testdata/TestMCPLoad/call1-resp.golden new file mode 100644 index 00000000..2861a036 --- /dev/null +++ b/pkg/tests/testdata/TestMCPLoad/call1-resp.golden @@ -0,0 +1,9 @@ +`{ + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 1" + } + ], + "usage": {} +}` diff --git a/pkg/tests/testdata/TestMCPLoad/call1.golden b/pkg/tests/testdata/TestMCPLoad/call1.golden new file mode 100644 index 00000000..31048a88 --- /dev/null +++ b/pkg/tests/testdata/TestMCPLoad/call1.golden @@ -0,0 +1,3 @@ +`{ + "model": "gpt-4o" +}` diff --git a/pkg/tests/testdata/TestMCPLoad/step1.golden b/pkg/tests/testdata/TestMCPLoad/step1.golden new file mode 100644 index 00000000..c5961afa --- /dev/null +++ b/pkg/tests/testdata/TestMCPLoad/step1.golden @@ -0,0 +1,6 @@ +`{ + "done": true, + "content": "{\"isError\":false,\"content\":[{\"type\":\"text\",\"text\":\"[{'1': 1}]\"}]}", + "toolID": "", + "state": null +}` diff --git a/pkg/tests/testdata/TestShareCreds/step1.golden b/pkg/tests/testdata/TestShareCreds/step1.golden new file mode 100644 index 00000000..9d584f92 --- /dev/null +++ b/pkg/tests/testdata/TestShareCreds/step1.golden @@ -0,0 +1,6 @@ +`{ + "done": true, + "content": "that worked\nthat also worked\n", + "toolID": "", + "state": null +}` diff --git a/pkg/tests/testdata/TestSubChat/call1.golden b/pkg/tests/testdata/TestSubChat/call1.golden index 0d906395..f0e0b491 100644 --- a/pkg/tests/testdata/TestSubChat/call1.golden +++ b/pkg/tests/testdata/TestSubChat/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestSubChat/test.gpt:chatbot", "name": "chatbot", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the assistant. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the assistant. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestSysContext/call1.golden b/pkg/tests/testdata/TestSysContext/call1.golden index 4c9c51d0..f1926c33 100644 --- a/pkg/tests/testdata/TestSysContext/call1.golden +++ b/pkg/tests/testdata/TestSysContext/call1.golden @@ -7,13 +7,13 @@ "toolID": "testdata/TestSysContext/file.gpt:I am Superman Agent", "name": "iAmSuperman", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestSysContext/step1.golden b/pkg/tests/testdata/TestSysContext/step1.golden index 426e5991..2755652a 100644 --- a/pkg/tests/testdata/TestSysContext/step1.golden +++ b/pkg/tests/testdata/TestSysContext/step1.golden @@ -15,13 +15,13 @@ "toolID": "testdata/TestSysContext/file.gpt:I am Superman Agent", "name": "iAmSuperman", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolAs/call1.golden b/pkg/tests/testdata/TestToolAs/call1.golden index 55796fea..758f9cca 100644 --- a/pkg/tests/testdata/TestToolAs/call1.golden +++ b/pkg/tests/testdata/TestToolAs/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestToolAs/test.gpt:infile", "name": "local", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestToolAs/other.gpt:", "name": "remote", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolRefAll/call1.golden b/pkg/tests/testdata/TestToolRefAll/call1.golden index 9289affa..2d7a7b08 100644 --- a/pkg/tests/testdata/TestToolRefAll/call1.golden +++ b/pkg/tests/testdata/TestToolRefAll/call1.golden @@ -6,13 +6,13 @@ "toolID": "testdata/TestToolRefAll/test.gpt:tool", "name": "tool", "parameters": { + "type": "object", "properties": { "toolArg": { - "description": "stuff", - "type": "string" + "type": "string", + "description": "stuff" } - }, - "type": "object" + } } } }, @@ -21,13 +21,13 @@ "toolID": "testdata/TestToolRefAll/test.gpt:agentAssistant", "name": "agentAssistant", "parameters": { + "type": "object", "properties": { "defaultPromptParameter": { - "description": "Prompt to send to the tool. This may be an instruction or question.", - "type": "string" + "type": "string", + "description": "Prompt to send to the tool. This may be an instruction or question." } - }, - "type": "object" + } } } }, @@ -36,13 +36,13 @@ "toolID": "testdata/TestToolRefAll/test.gpt:none", "name": "none", "parameters": { + "type": "object", "properties": { "noneArg": { - "description": "stuff", - "type": "string" + "type": "string", + "description": "stuff" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolsChange/call1.golden b/pkg/tests/testdata/TestToolsChange/call1.golden index 69ab3d03..8bbc8ed5 100644 --- a/pkg/tests/testdata/TestToolsChange/call1.golden +++ b/pkg/tests/testdata/TestToolsChange/call1.golden @@ -8,13 +8,13 @@ "name": "ls", "description": "Lists the contents of a directory", "parameters": { + "type": "object", "properties": { "dir": { - "description": "The directory to list", - "type": "string" + "type": "string", + "description": "The directory to list" } - }, - "type": "object" + } } } }, @@ -24,13 +24,13 @@ "name": "read", "description": "Reads the contents of a file. Can only read plain text files, not binary files", "parameters": { + "type": "object", "properties": { "filename": { - "description": "The name of the file to read", - "type": "string" + "type": "string", + "description": "The name of the file to read" } - }, - "type": "object" + } } } }, @@ -40,17 +40,17 @@ "name": "write", "description": "Write the contents to a file", "parameters": { + "type": "object", "properties": { "content": { - "description": "The content to write", - "type": "string" + "type": "string", + "description": "The content to write" }, "filename": { - "description": "The name of the file to write to", - "type": "string" + "type": "string", + "description": "The name of the file to write to" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolsChange/call2.golden b/pkg/tests/testdata/TestToolsChange/call2.golden index ad86b7ce..4abdfddf 100644 --- a/pkg/tests/testdata/TestToolsChange/call2.golden +++ b/pkg/tests/testdata/TestToolsChange/call2.golden @@ -8,13 +8,13 @@ "name": "ls", "description": "Lists the contents of a directory", "parameters": { + "type": "object", "properties": { "dir": { - "description": "The directory to list", - "type": "string" + "type": "string", + "description": "The directory to list" } - }, - "type": "object" + } } } }, @@ -24,17 +24,17 @@ "name": "write", "description": "Write the contents to a file", "parameters": { + "type": "object", "properties": { "content": { - "description": "The content to write", - "type": "string" + "type": "string", + "description": "The content to write" }, "filename": { - "description": "The name of the file to write to", - "type": "string" + "type": "string", + "description": "The name of the file to write to" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolsChange/step1.golden b/pkg/tests/testdata/TestToolsChange/step1.golden index e26862ae..2274f8b0 100644 --- a/pkg/tests/testdata/TestToolsChange/step1.golden +++ b/pkg/tests/testdata/TestToolsChange/step1.golden @@ -16,13 +16,13 @@ "name": "ls", "description": "Lists the contents of a directory", "parameters": { + "type": "object", "properties": { "dir": { - "description": "The directory to list", - "type": "string" + "type": "string", + "description": "The directory to list" } - }, - "type": "object" + } } } }, @@ -32,13 +32,13 @@ "name": "read", "description": "Reads the contents of a file. Can only read plain text files, not binary files", "parameters": { + "type": "object", "properties": { "filename": { - "description": "The name of the file to read", - "type": "string" + "type": "string", + "description": "The name of the file to read" } - }, - "type": "object" + } } } }, @@ -48,17 +48,17 @@ "name": "write", "description": "Write the contents to a file", "parameters": { + "type": "object", "properties": { "content": { - "description": "The content to write", - "type": "string" + "type": "string", + "description": "The content to write" }, "filename": { - "description": "The name of the file to write to", - "type": "string" + "type": "string", + "description": "The name of the file to write to" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/testdata/TestToolsChange/step2.golden b/pkg/tests/testdata/TestToolsChange/step2.golden index 9c9dbad7..ef99f90e 100644 --- a/pkg/tests/testdata/TestToolsChange/step2.golden +++ b/pkg/tests/testdata/TestToolsChange/step2.golden @@ -16,13 +16,13 @@ "name": "ls", "description": "Lists the contents of a directory", "parameters": { + "type": "object", "properties": { "dir": { - "description": "The directory to list", - "type": "string" + "type": "string", + "description": "The directory to list" } - }, - "type": "object" + } } } }, @@ -32,17 +32,17 @@ "name": "write", "description": "Write the contents to a file", "parameters": { + "type": "object", "properties": { "content": { - "description": "The content to write", - "type": "string" + "type": "string", + "description": "The content to write" }, "filename": { - "description": "The name of the file to write to", - "type": "string" + "type": "string", + "description": "The name of the file to write to" } - }, - "type": "object" + } } } } diff --git a/pkg/tests/tester/runner.go b/pkg/tests/tester/runner.go index b460ce18..f59c0b14 100644 --- a/pkg/tests/tester/runner.go +++ b/pkg/tests/tester/runner.go @@ -31,11 +31,11 @@ type Result struct { Err error } -func (c *Client) ProxyInfo() (string, string, error) { +func (c *Client) ProxyInfo([]string) (string, string, error) { return "test-auth", "test-url", nil } -func (c *Client) Call(_ context.Context, messageRequest types.CompletionRequest, _ chan<- types.CompletionStatus) (resp *types.CompletionMessage, respErr error) { +func (c *Client) Call(_ context.Context, messageRequest types.CompletionRequest, _ []string, _ chan<- types.CompletionStatus) (resp *types.CompletionMessage, respErr error) { msgData, err := json.MarshalIndent(messageRequest, "", " ") require.NoError(c.t, err) @@ -159,7 +159,7 @@ func (r *Runner) Run(script, input string) (string, error) { return "", err } - return r.Runner.Run(context.Background(), prg, os.Environ(), input) + return r.Runner.Run(context.Background(), prg, os.Environ(), input, runner.RunOptions{}) } func (r *Runner) AssertResponded(t *testing.T) { @@ -196,7 +196,7 @@ func NewRunner(t *testing.T) *Runner { cacheDir, err := xdg.CacheFile("gptscript-test-cache/runtime") require.NoError(t, err) - rm := runtimes.Default(cacheDir) + rm := runtimes.Default(cacheDir, "") run, err := runner.New(c, credentials.NoopStore{}, runner.Options{ Sequential: true, diff --git a/pkg/types/args.go b/pkg/types/args.go new file mode 100644 index 00000000..62933de1 --- /dev/null +++ b/pkg/types/args.go @@ -0,0 +1,99 @@ +//nolint:revive +package types + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/google/shlex" +) + +func GetToolRefInput(prg *Program, ref ToolReference, input string) (string, error) { + if ref.Arg == "" { + return "", nil + } + + targetArgs := prg.ToolSet[ref.ToolID].Arguments + targetKeys := map[string]string{} + + if ref.Arg == "*" { + return input, nil + } + + if targetArgs == nil { + return "", nil + } + + for targetKey := range targetArgs.Properties { + targetKeys[strings.ToLower(targetKey)] = targetKey + } + + inputMap := map[string]interface{}{} + outputMap := map[string]interface{}{} + + _ = json.Unmarshal([]byte(input), &inputMap) + for k, v := range inputMap { + inputMap[strings.ToLower(k)] = v + } + + fields, err := shlex.Split(ref.Arg) + if err != nil { + return "", fmt.Errorf("invalid tool args %q: %v", ref.Arg, err) + } + + for i := 0; i < len(fields); i++ { + field := fields[i] + if field == "and" { + continue + } + if field == "as" { + i++ + continue + } + + var ( + keyName string + val any + ) + + if strings.HasPrefix(field, "$") { + key := strings.TrimPrefix(field, "$") + key = strings.TrimPrefix(key, "{") + key = strings.TrimSuffix(key, "}") + val = inputMap[strings.ToLower(key)] + } else { + val = field + } + + if len(fields) > i+1 && fields[i+1] == "as" { + keyName = strings.ToLower(fields[i+2]) + } + + if len(targetKeys) == 0 { + return "", fmt.Errorf("can not assign arg to context because target tool [%s] has no defined args", ref.ToolID) + } + + if keyName == "" { + if len(targetKeys) != 1 { + return "", fmt.Errorf("can not assign arg to context because target tool [%s] does not have one args. You must use \"as\" syntax to map the arg to a key %v", ref.ToolID, targetKeys) + } + for k := range targetKeys { + keyName = k + } + } + + if targetKey, ok := targetKeys[strings.ToLower(keyName)]; ok { + outputMap[targetKey] = val + } else { + return "", fmt.Errorf("can not assign arg to context because target tool [%s] does not args [%s]", ref.ToolID, keyName) + } + } + + if len(outputMap) == 0 { + return "", nil + } + + output, err := json.Marshal(outputMap) + return string(output), err +} diff --git a/pkg/types/completion.go b/pkg/types/completion.go index 5b3899c3..bacdaab8 100644 --- a/pkg/types/completion.go +++ b/pkg/types/completion.go @@ -1,11 +1,11 @@ +//nolint:revive package types import ( "fmt" "strings" - "github.com/fatih/color" - "github.com/getkin/kin-openapi/openapi3" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) type CompletionRequest struct { @@ -32,10 +32,10 @@ type ChatCompletionTool struct { } type CompletionFunctionDefinition struct { - ToolID string `json:"toolID,omitempty"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - Parameters *openapi3.Schema `json:"parameters"` + ToolID string `json:"toolID,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Parameters *jsonschema.Schema `json:"parameters"` } // Chat message role defined by the OpenAI API. @@ -83,7 +83,6 @@ type CompletionStatus struct { Response any Usage Usage Cached bool - Chunks any PartialResponse *CompletionMessage } @@ -112,7 +111,7 @@ func (c CompletionMessage) String() string { } buf.WriteString(content.Text) if content.ToolCall != nil { - buf.WriteString(fmt.Sprintf(" %s -> %s", color.GreenString(content.ToolCall.Function.Name), content.ToolCall.Function.Arguments)) + buf.WriteString(fmt.Sprintf(" %s -> %s", content.ToolCall.Function.Name, content.ToolCall.Function.Arguments)) } } return buf.String() diff --git a/pkg/types/credential_test.go b/pkg/types/credential_test.go index b6f70ee3..7f03e2d9 100644 --- a/pkg/types/credential_test.go +++ b/pkg/types/credential_test.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( @@ -9,13 +10,14 @@ import ( func TestParseCredentialArgs(t *testing.T) { tests := []struct { - name string - toolName string - input string - expectedName string - expectedAlias string - expectedArgs map[string]string - wantErr bool + name string + toolName string + input string + expectedName string + expectedAlias string + expectedCheckParam string + expectedArgs map[string]string + wantErr bool }{ { name: "empty", @@ -94,6 +96,40 @@ func TestParseCredentialArgs(t *testing.T) { "arg2": "value2", }, }, + { + name: "tool name with check parameter", + toolName: `myCredentialTool checked with myCheckParam`, + expectedName: "myCredentialTool", + expectedCheckParam: "myCheckParam", + }, + { + name: "tool name with alias and check parameter", + toolName: `myCredentialTool as myAlias checked with myCheckParam`, + expectedName: "myCredentialTool", + expectedAlias: "myAlias", + expectedCheckParam: "myCheckParam", + }, + { + name: "tool name with alias, check parameter, and args", + toolName: `myCredentialTool as myAlias checked with myCheckParam with value1 as arg1 and value2 as arg2`, + expectedName: "myCredentialTool", + expectedAlias: "myAlias", + expectedCheckParam: "myCheckParam", + expectedArgs: map[string]string{ + "arg1": "value1", + "arg2": "value2", + }, + }, + { + name: "check parameter without with", + toolName: `myCredentialTool checked myCheckParam`, + wantErr: true, + }, + { + name: "invalid check parameter", + toolName: `myCredentialTool checked with`, + wantErr: true, + }, { name: "tool name with alias but no 'as' (invalid)", toolName: "myCredentialTool myAlias", @@ -136,7 +172,7 @@ func TestParseCredentialArgs(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - originalName, alias, args, err := ParseCredentialArgs(tt.toolName, tt.input) + originalName, alias, checkParam, args, err := ParseCredentialArgs(tt.toolName, tt.input) if tt.wantErr { require.Error(t, err, "expected an error but got none") return @@ -145,6 +181,7 @@ func TestParseCredentialArgs(t *testing.T) { require.NoError(t, err, "did not expect an error but got one") require.Equal(t, tt.expectedName, originalName, "unexpected original name") require.Equal(t, tt.expectedAlias, alias, "unexpected alias") + require.Equal(t, tt.expectedCheckParam, checkParam, "unexpected checkParam") require.Equal(t, len(tt.expectedArgs), len(args), "unexpected number of args") for k, v := range tt.expectedArgs { diff --git a/pkg/types/jsonschema.go b/pkg/types/jsonschema.go index 6fd0d4ea..17df0692 100644 --- a/pkg/types/jsonschema.go +++ b/pkg/types/jsonschema.go @@ -1,21 +1,18 @@ +//nolint:revive package types -import ( - "github.com/getkin/kin-openapi/openapi3" -) +import "github.com/modelcontextprotocol/go-sdk/jsonschema" -func ObjectSchema(kv ...string) *openapi3.Schema { - s := &openapi3.Schema{ - Type: &openapi3.Types{"object"}, - Properties: openapi3.Schemas{}, +func ObjectSchema(kv ...string) *jsonschema.Schema { + s := &jsonschema.Schema{ + Type: "object", + Properties: make(map[string]*jsonschema.Schema, len(kv)/2), } for i, v := range kv { if i%2 == 1 { - s.Properties[kv[i-1]] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: v, - Type: &openapi3.Types{"string"}, - }, + s.Properties[kv[i-1]] = &jsonschema.Schema{ + Description: v, + Type: "string", } } } diff --git a/pkg/types/log.go b/pkg/types/log.go index ba3ff8c5..de23ece8 100644 --- a/pkg/types/log.go +++ b/pkg/types/log.go @@ -1,3 +1,4 @@ +//nolint:revive package types import "github.com/gptscript-ai/gptscript/pkg/mvl" diff --git a/pkg/types/prompt.go b/pkg/types/prompt.go index 653ad066..42e6eaa5 100644 --- a/pkg/types/prompt.go +++ b/pkg/types/prompt.go @@ -1,5 +1,11 @@ +//nolint:revive package types +import ( + "encoding/json" + "strings" +) + const ( PromptURLEnvVar = "GPTSCRIPT_PROMPT_URL" PromptTokenEnvVar = "GPTSCRIPT_PROMPT_TOKEN" @@ -7,7 +13,64 @@ const ( type Prompt struct { Message string `json:"message,omitempty"` - Fields []string `json:"fields,omitempty"` + Fields Fields `json:"fields,omitempty"` Sensitive bool `json:"sensitive,omitempty"` Metadata map[string]string `json:"metadata,omitempty"` } + +type Field struct { + Name string `json:"name,omitempty"` + Sensitive *bool `json:"sensitive,omitempty"` + Description string `json:"description,omitempty"` + Options []string `json:"options,omitempty"` +} + +type Fields []Field + +// UnmarshalJSON will unmarshal the corresponding JSON object for Fields, +// or a comma-separated strings (for backwards compatibility). +func (f *Fields) UnmarshalJSON(b []byte) error { + if len(b) == 0 || f == nil { + return nil + } + + if b[0] == '[' { + var arr []Field + if err := json.Unmarshal(b, &arr); err != nil { + return err + } + *f = arr + return nil + } + + var fields string + if err := json.Unmarshal(b, &fields); err != nil { + return err + } + + if fields != "" { + fieldsArr := strings.Split(fields, ",") + *f = make([]Field, 0, len(fieldsArr)) + for _, field := range fieldsArr { + *f = append(*f, Field{Name: strings.TrimSpace(field)}) + } + } + + return nil +} + +type field *Field + +// UnmarshalJSON will unmarshal the corresponding JSON object for a Field, +// or a string (for backwards compatibility). +func (f *Field) UnmarshalJSON(b []byte) error { + if len(b) == 0 || f == nil { + return nil + } + + if b[0] == '{' { + return json.Unmarshal(b, field(f)) + } + + return json.Unmarshal(b, &f.Name) +} diff --git a/pkg/types/prompt_test.go b/pkg/types/prompt_test.go new file mode 100644 index 00000000..c081011e --- /dev/null +++ b/pkg/types/prompt_test.go @@ -0,0 +1,143 @@ +//nolint:revive +package types + +import ( + "reflect" + "testing" +) + +func TestFieldUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + input []byte + expected Field + expectErr bool + }{ + { + name: "valid single Field object JSON", + input: []byte(`{"name":"field1","sensitive":true,"description":"A test field"}`), + expected: Field{Name: "field1", Sensitive: boolPtr(true), Description: "A test field"}, + expectErr: false, + }, + { + name: "valid Field name as string", + input: []byte(`"field1"`), + expected: Field{Name: "field1"}, + expectErr: false, + }, + { + name: "empty input", + input: []byte(``), + expected: Field{}, + expectErr: false, + }, + { + name: "invalid JSON object", + input: []byte(`{"name":"field1","sensitive":"not_boolean"}`), + expected: Field{Name: "field1", Sensitive: new(bool)}, + expectErr: true, + }, + { + name: "extra unknown fields in JSON object", + input: []byte(`{"name":"field1","unknown":"field","sensitive":false}`), + expected: Field{Name: "field1", Sensitive: boolPtr(false)}, + expectErr: false, + }, + { + name: "malformed JSON", + input: []byte(`{"name":"field1","sensitive":true`), + expected: Field{}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var field Field + err := field.UnmarshalJSON(tt.input) + if (err != nil) != tt.expectErr { + t.Errorf("UnmarshalJSON() error = %v, expectErr %v", err, tt.expectErr) + } + if !reflect.DeepEqual(field, tt.expected) { + t.Errorf("UnmarshalJSON() = %v, expected %v", field, tt.expected) + } + }) + } +} + +func TestFieldsUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + input []byte + expected Fields + expectErr bool + }{ + { + name: "empty input", + input: nil, + expected: nil, + expectErr: false, + }, + { + name: "nil pointer", + input: nil, + expected: nil, + expectErr: false, + }, + { + name: "valid JSON array", + input: []byte(`[{"Name":"field1"},{"Name":"field2"}]`), + expected: Fields{{Name: "field1"}, {Name: "field2"}}, + expectErr: false, + }, + { + name: "single string input", + input: []byte(`"field1,field2,field3"`), + expected: Fields{{Name: "field1"}, {Name: "field2"}, {Name: "field3"}}, + expectErr: false, + }, + { + name: "trim spaces in single string input", + input: []byte(`"field1, field2 , field3 "`), + expected: Fields{{Name: "field1"}, {Name: "field2"}, {Name: "field3"}}, + expectErr: false, + }, + { + name: "invalid JSON array", + input: []byte(`[{"Name":"field1"},{"Name":field2}]`), + expected: nil, + expectErr: true, + }, + { + name: "invalid single string", + input: []byte(`1234`), + expected: nil, + expectErr: true, + }, + { + name: "empty array", + input: []byte(`[]`), + expected: Fields{}, + expectErr: false, + }, + { + name: "empty string", + input: []byte(`""`), + expected: nil, + expectErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var fields Fields + err := fields.UnmarshalJSON(tt.input) + if (err != nil) != tt.expectErr { + t.Errorf("UnmarshalJSON() error = %v, expectErr %v", err, tt.expectErr) + } + if !reflect.DeepEqual(fields, tt.expected) { + t.Errorf("UnmarshalJSON() = %v, expected %v", fields, tt.expected) + } + }) + } +} diff --git a/pkg/types/set.go b/pkg/types/set.go index 65b73d22..654fbd5f 100644 --- a/pkg/types/set.go +++ b/pkg/types/set.go @@ -1,3 +1,4 @@ +//nolint:revive package types type toolRefKey struct { diff --git a/pkg/types/tool.go b/pkg/types/tool.go index 0bd7bc02..42b08f62 100644 --- a/pkg/types/tool.go +++ b/pkg/types/tool.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( @@ -9,17 +10,21 @@ import ( "sort" "strings" - "github.com/getkin/kin-openapi/openapi3" "github.com/google/shlex" "github.com/gptscript-ai/gptscript/pkg/system" + "github.com/modelcontextprotocol/go-sdk/jsonschema" "golang.org/x/exp/maps" ) const ( - DaemonPrefix = "#!sys.daemon" - OpenAPIPrefix = "#!sys.openapi" - EchoPrefix = "#!sys.echo" - CommandPrefix = "#!" + DaemonPrefix = "#!sys.daemon" + OpenAPIPrefix = "#!sys.openapi" + EchoPrefix = "#!sys.echo" + CallPrefix = "#!sys.call" + MCPPrefix = "#!mcp" + MCPInvokePrefix = "#!sys.mcp.invoke." + CommandPrefix = "#!" + PromptPrefix = "!!" ) var ( @@ -116,32 +121,33 @@ func (p Program) SetBlocking() Program { type BuiltinFunc func(ctx context.Context, env []string, input string, progress chan<- string) (string, error) type Parameters struct { - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - MaxTokens int `json:"maxTokens,omitempty"` - ModelName string `json:"modelName,omitempty"` - ModelProvider bool `json:"modelProvider,omitempty"` - JSONResponse bool `json:"jsonResponse,omitempty"` - Chat bool `json:"chat,omitempty"` - Temperature *float32 `json:"temperature,omitempty"` - Cache *bool `json:"cache,omitempty"` - InternalPrompt *bool `json:"internalPrompt"` - Arguments *openapi3.Schema `json:"arguments,omitempty"` - Tools []string `json:"tools,omitempty"` - GlobalTools []string `json:"globalTools,omitempty"` - GlobalModelName string `json:"globalModelName,omitempty"` - Context []string `json:"context,omitempty"` - ExportContext []string `json:"exportContext,omitempty"` - Export []string `json:"export,omitempty"` - Agents []string `json:"agents,omitempty"` - Credentials []string `json:"credentials,omitempty"` - ExportCredentials []string `json:"exportCredentials,omitempty"` - InputFilters []string `json:"inputFilters,omitempty"` - ExportInputFilters []string `json:"exportInputFilters,omitempty"` - OutputFilters []string `json:"outputFilters,omitempty"` - ExportOutputFilters []string `json:"exportOutputFilters,omitempty"` - Blocking bool `json:"-"` - Type ToolType `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + MaxTokens int `json:"maxTokens,omitempty"` + ModelName string `json:"modelName,omitempty"` + ModelProvider bool `json:"modelProvider,omitempty"` + JSONResponse bool `json:"jsonResponse,omitempty"` + Chat bool `json:"chat,omitempty"` + Temperature *float32 `json:"temperature,omitempty"` + Cache *bool `json:"cache,omitempty"` + InternalPrompt *bool `json:"internalPrompt"` + Arguments *jsonschema.Schema `json:"arguments,omitempty"` + Tools []string `json:"tools,omitempty"` + GlobalTools []string `json:"globalTools,omitempty"` + GlobalModelName string `json:"globalModelName,omitempty"` + Context []string `json:"context,omitempty"` + ExportContext []string `json:"exportContext,omitempty"` + Export []string `json:"export,omitempty"` + Agents []string `json:"agents,omitempty"` + Credentials []string `json:"credentials,omitempty"` + ExportCredentials []string `json:"exportCredentials,omitempty"` + InputFilters []string `json:"inputFilters,omitempty"` + ExportInputFilters []string `json:"exportInputFilters,omitempty"` + OutputFilters []string `json:"outputFilters,omitempty"` + ExportOutputFilters []string `json:"exportOutputFilters,omitempty"` + Blocking bool `json:"-"` + Stdin bool `json:"stdin,omitempty"` + Type ToolType `json:"type,omitempty"` } func (p Parameters) allExports() []string { @@ -270,9 +276,9 @@ func SplitArg(hasArg string) (prefix, arg string) { // - toolName: "toolName with ${var1} as arg1 and ${var2} as arg2" // - input: `{"var1": "value1", "var2": "value2"}` // result: toolName, "", map[string]any{"arg1": "value1", "arg2": "value2"}, nil -func ParseCredentialArgs(toolName string, input string) (string, string, map[string]any, error) { +func ParseCredentialArgs(toolName string, input string) (string, string, string, map[string]any, error) { if toolName == "" { - return "", "", nil, nil + return "", "", "", nil, nil } inputMap := make(map[string]any) @@ -285,12 +291,12 @@ func ParseCredentialArgs(toolName string, input string) (string, string, map[str fields, err := shlex.Split(toolName) if err != nil { - return "", "", nil, err + return "", "", "", nil, err } // If it's just the tool name, return it if len(fields) == 1 { - return toolName, "", nil, nil + return toolName, "", "", nil, nil } // Next field is "as" if there is an alias, otherwise it should be "with" @@ -299,25 +305,39 @@ func ParseCredentialArgs(toolName string, input string) (string, string, map[str fields = fields[1:] if fields[0] == "as" { if len(fields) < 2 { - return "", "", nil, fmt.Errorf("expected alias after 'as'") + return "", "", "", nil, fmt.Errorf("expected alias after 'as'") } alias = fields[1] fields = fields[2:] } if len(fields) == 0 { // Nothing left, so just return - return originalName, alias, nil, nil + return originalName, alias, "", nil, nil + } + + var checkParam string + if fields[0] == "checked" { + if len(fields) < 3 || fields[1] != "with" { + return "", "", "", nil, fmt.Errorf("expected 'checked with some_value' but got %v", fields) + } + + checkParam = fields[2] + fields = fields[3:] + } + + if len(fields) == 0 { // Nothing left, so just return + return originalName, alias, checkParam, nil, nil } // Next we should have "with" followed by the args if fields[0] != "with" { - return "", "", nil, fmt.Errorf("expected 'with' but got %s", fields[0]) + return "", "", "", nil, fmt.Errorf("expected 'with' but got %s", fields[0]) } fields = fields[1:] // If there are no args, return an error if len(fields) == 0 { - return "", "", nil, fmt.Errorf("expected args after 'with'") + return "", "", "", nil, fmt.Errorf("expected args after 'with'") } args := make(map[string]any) @@ -330,7 +350,7 @@ func ParseCredentialArgs(toolName string, input string) (string, string, map[str prev = "value" case "value": if field != "as" { - return "", "", nil, fmt.Errorf("expected 'as' but got %s", field) + return "", "", "", nil, fmt.Errorf("expected 'as' but got %s", field) } prev = "as" case "as": @@ -338,14 +358,14 @@ func ParseCredentialArgs(toolName string, input string) (string, string, map[str prev = "name" case "name": if field != "and" { - return "", "", nil, fmt.Errorf("expected 'and' but got %s", field) + return "", "", "", nil, fmt.Errorf("expected 'and' but got %s", field) } prev = "and" } } if prev == "and" { - return "", "", nil, fmt.Errorf("expected arg name after 'and'") + return "", "", "", nil, fmt.Errorf("expected arg name after 'and'") } // Check and see if any of the arg values are references to an input @@ -358,7 +378,7 @@ func ParseCredentialArgs(toolName string, input string) (string, string, map[str } } - return originalName, alias, args, nil + return originalName, alias, checkParam, args, nil } func (t Tool) GetToolRefsFromNames(names []string) (result []ToolReference, _ error) { @@ -387,98 +407,122 @@ func (t Tool) GetToolRefsFromNames(names []string) (result []ToolReference, _ er } func (t ToolDef) String() string { + data, err := json.Marshal([]any{t}) + if err != nil { + panic(err) + } + return "#!GPTSCRIPT" + string(data) +} + +func (t ToolDef) Print() string { buf := &strings.Builder{} - if t.Parameters.GlobalModelName != "" { - _, _ = fmt.Fprintf(buf, "Global Model Name: %s\n", t.Parameters.GlobalModelName) + if t.GlobalModelName != "" { + _, _ = fmt.Fprintf(buf, "Global Model Name: %s\n", t.GlobalModelName) } - if len(t.Parameters.GlobalTools) != 0 { - _, _ = fmt.Fprintf(buf, "Global Tools: %s\n", strings.Join(t.Parameters.GlobalTools, ", ")) + if len(t.GlobalTools) != 0 { + _, _ = fmt.Fprintf(buf, "Global Tools: %s\n", strings.Join(t.GlobalTools, ", ")) } - if t.Parameters.Name != "" { - _, _ = fmt.Fprintf(buf, "Name: %s\n", t.Parameters.Name) + if t.Name != "" { + _, _ = fmt.Fprintf(buf, "Name: %s\n", t.Name) } - if t.Parameters.Description != "" { - _, _ = fmt.Fprintf(buf, "Description: %s\n", t.Parameters.Description) + if t.Description != "" { + _, _ = fmt.Fprintf(buf, "Description: %s\n", t.Description) } - if t.Parameters.Type != ToolTypeDefault { + if t.Type != ToolTypeDefault { _, _ = fmt.Fprintf(buf, "Type: %s\n", strings.ToUpper(string(t.Type[0]))+string(t.Type[1:])) } - if len(t.Parameters.Agents) != 0 { - _, _ = fmt.Fprintf(buf, "Agents: %s\n", strings.Join(t.Parameters.Agents, ", ")) + if len(t.Agents) != 0 { + _, _ = fmt.Fprintf(buf, "Agents: %s\n", strings.Join(t.Agents, ", ")) } - if len(t.Parameters.Tools) != 0 { - _, _ = fmt.Fprintf(buf, "Tools: %s\n", strings.Join(t.Parameters.Tools, ", ")) + if len(t.Tools) != 0 { + _, _ = fmt.Fprintf(buf, "Tools: %s\n", strings.Join(t.Tools, ", ")) } - if len(t.Parameters.Export) != 0 { - _, _ = fmt.Fprintf(buf, "Share Tools: %s\n", strings.Join(t.Parameters.Export, ", ")) + if len(t.Export) != 0 { + _, _ = fmt.Fprintf(buf, "Share Tools: %s\n", strings.Join(t.Export, ", ")) } - if len(t.Parameters.Context) != 0 { - _, _ = fmt.Fprintf(buf, "Context: %s\n", strings.Join(t.Parameters.Context, ", ")) + if len(t.Context) != 0 { + _, _ = fmt.Fprintf(buf, "Context: %s\n", strings.Join(t.Context, ", ")) } - if len(t.Parameters.ExportContext) != 0 { - _, _ = fmt.Fprintf(buf, "Share Context: %s\n", strings.Join(t.Parameters.ExportContext, ", ")) + if len(t.ExportContext) != 0 { + _, _ = fmt.Fprintf(buf, "Share Context: %s\n", strings.Join(t.ExportContext, ", ")) } - if len(t.Parameters.InputFilters) != 0 { - _, _ = fmt.Fprintf(buf, "Input Filters: %s\n", strings.Join(t.Parameters.InputFilters, ", ")) + if len(t.InputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Input Filters: %s\n", strings.Join(t.InputFilters, ", ")) } - if len(t.Parameters.ExportInputFilters) != 0 { - _, _ = fmt.Fprintf(buf, "Share Input Filters: %s\n", strings.Join(t.Parameters.ExportInputFilters, ", ")) + if len(t.ExportInputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Share Input Filters: %s\n", strings.Join(t.ExportInputFilters, ", ")) } - if len(t.Parameters.OutputFilters) != 0 { - _, _ = fmt.Fprintf(buf, "Output Filters: %s\n", strings.Join(t.Parameters.OutputFilters, ", ")) + if len(t.OutputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Output Filters: %s\n", strings.Join(t.OutputFilters, ", ")) } - if len(t.Parameters.ExportOutputFilters) != 0 { - _, _ = fmt.Fprintf(buf, "Share Output Filters: %s\n", strings.Join(t.Parameters.ExportOutputFilters, ", ")) + if len(t.ExportOutputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Share Output Filters: %s\n", strings.Join(t.ExportOutputFilters, ", ")) } - if t.Parameters.MaxTokens != 0 { - _, _ = fmt.Fprintf(buf, "Max Tokens: %d\n", t.Parameters.MaxTokens) + if t.MaxTokens != 0 { + _, _ = fmt.Fprintf(buf, "Max Tokens: %d\n", t.MaxTokens) } - if t.Parameters.ModelName != "" { - _, _ = fmt.Fprintf(buf, "Model: %s\n", t.Parameters.ModelName) + if t.ModelName != "" { + _, _ = fmt.Fprintf(buf, "Model: %s\n", t.ModelName) } - if t.Parameters.ModelProvider { + if t.ModelProvider { _, _ = fmt.Fprintf(buf, "Model Provider: true\n") } - if t.Parameters.JSONResponse { + if t.JSONResponse { _, _ = fmt.Fprintln(buf, "JSON Response: true") } - if t.Parameters.Cache != nil && !*t.Parameters.Cache { + if t.Cache != nil && !*t.Cache { _, _ = fmt.Fprintln(buf, "Cache: false") } - if t.Parameters.Temperature != nil { - _, _ = fmt.Fprintf(buf, "Temperature: %f\n", *t.Parameters.Temperature) + if t.Stdin { + _, _ = fmt.Fprintln(buf, "Stdin: true") + } + if t.Temperature != nil { + _, _ = fmt.Fprintf(buf, "Temperature: %f\n", *t.Temperature) } - if t.Parameters.Arguments != nil { + if t.Arguments != nil { var keys []string - for k := range t.Parameters.Arguments.Properties { + for k := range t.Arguments.Properties { keys = append(keys, k) } sort.Strings(keys) for _, key := range keys { - prop := t.Parameters.Arguments.Properties[key] - _, _ = fmt.Fprintf(buf, "Parameter: %s: %s\n", key, prop.Value.Description) + prop := t.Arguments.Properties[key] + _, _ = fmt.Fprintf(buf, "Parameter: %s: %s\n", key, prop.Description) } } - if t.Parameters.InternalPrompt != nil { - _, _ = fmt.Fprintf(buf, "Internal Prompt: %v\n", *t.Parameters.InternalPrompt) + if t.InternalPrompt != nil { + _, _ = fmt.Fprintf(buf, "Internal Prompt: %v\n", *t.InternalPrompt) } - if len(t.Parameters.Credentials) > 0 { - for _, cred := range t.Parameters.Credentials { + if len(t.Credentials) > 0 { + for _, cred := range t.Credentials { _, _ = fmt.Fprintf(buf, "Credential: %s\n", cred) } } - if len(t.Parameters.ExportCredentials) > 0 { - for _, exportCred := range t.Parameters.ExportCredentials { + if len(t.ExportCredentials) > 0 { + for _, exportCred := range t.ExportCredentials { _, _ = fmt.Fprintf(buf, "Share Credential: %s\n", exportCred) } } - if t.Parameters.Chat { + if t.Chat { _, _ = fmt.Fprintf(buf, "Chat: true\n") } + keys := maps.Keys(t.MetaData) + sort.Strings(keys) + for _, key := range keys { + value := t.MetaData[key] + if !strings.Contains(value, "\n") { + _, _ = fmt.Fprintf(buf, "Meta Data: %s: %s\n", key, value) + } + } + // Instructions should be printed last if t.Instructions != "" && t.BuiltinFunc == nil { - _, _ = fmt.Fprintln(buf) + if strings.Contains(strings.Split(strings.TrimSpace(t.Instructions), "\n")[0], ":") { + _, _ = fmt.Fprintln(buf, "===") + } else { + _, _ = fmt.Fprintln(buf) + } _, _ = fmt.Fprintln(buf, t.Instructions) } @@ -486,14 +530,17 @@ func (t ToolDef) String() string { keys := maps.Keys(t.MetaData) sort.Strings(keys) for _, key := range keys { - buf.WriteString("---\n") - buf.WriteString("!metadata:") - buf.WriteString(t.Name) - buf.WriteString(":") - buf.WriteString(key) - buf.WriteString("\n") - buf.WriteString(t.MetaData[key]) - buf.WriteString("\n") + value := t.MetaData[key] + if strings.Contains(value, "\n") { + buf.WriteString("---\n") + buf.WriteString("!metadata:") + buf.WriteString(t.Name) + buf.WriteString(":") + buf.WriteString(key) + buf.WriteString("\n") + buf.WriteString(t.MetaData[key]) + buf.WriteString("\n") + } } } @@ -512,6 +559,56 @@ func (t Tool) GetNextAgentGroup(prg *Program, agentGroup []ToolReference, toolID return agentGroup, nil } +func (t Tool) getCredentials(prg *Program) (result []ToolReference, _ error) { + toolRefs, err := t.GetToolRefsFromNames(t.Credentials) + if err != nil { + return nil, err + } + + for _, toolRef := range toolRefs { + tool, ok := prg.ToolSet[toolRef.ToolID] + if !ok { + continue + } + + if !tool.IsNoop() { + result = append(result, toolRef) + } + + shared, err := tool.getSharedCredentials(prg) + if err != nil { + return nil, err + } + result = append(result, shared...) + } + + return result, nil +} + +func (t Tool) getSharedCredentials(prg *Program) (result []ToolReference, _ error) { + toolRefs, err := t.GetToolRefsFromNames(t.ExportCredentials) + if err != nil { + return nil, err + } + for _, toolRef := range toolRefs { + tool, ok := prg.ToolSet[toolRef.ToolID] + if !ok { + continue + } + + if !tool.IsNoop() { + result = append(result, toolRef) + } + + nested, err := tool.getSharedCredentials(prg) + if err != nil { + return nil, err + } + result = append(result, nested...) + } + return result, nil +} + func (t Tool) getAgents(prg *Program) (result []ToolReference, _ error) { toolRefs, err := t.GetToolRefsFromNames(t.Agents) if err != nil { @@ -539,9 +636,13 @@ func (t Tool) getAgents(prg *Program) (result []ToolReference, _ error) { } func (t Tool) GetToolsByType(prg *Program, toolType ToolType) ([]ToolReference, error) { - if toolType == ToolTypeAgent { + switch toolType { + case ToolTypeAgent: // Agents are special, they can only be sourced from direct references and not the generic 'tool:' or shared by references return t.getAgents(prg) + case ToolTypeCredential: + // Credentials are special too, you can only get shared credentials from directly referenced credentials + return t.getCredentials(prg) } toolSet := &toolRefSet{} @@ -560,8 +661,6 @@ func (t Tool) GetToolsByType(prg *Program, toolType ToolType) ([]ToolReference, directRefs = t.InputFilters case ToolTypeTool: toolsListFilterType = append(toolsListFilterType, ToolTypeDefault, ToolTypeAgent) - case ToolTypeCredential: - directRefs = t.Credentials default: return nil, fmt.Errorf("unknown tool type %v", toolType) } @@ -602,8 +701,6 @@ func (t Tool) GetToolsByType(prg *Program, toolType ToolType) ([]ToolReference, case ToolTypeInput: exportRefs = tool.ExportInputFilters case ToolTypeTool: - case ToolTypeCredential: - exportRefs = tool.ExportCredentials default: return nil, fmt.Errorf("unknown tool type %v", toolType) } @@ -706,7 +803,7 @@ func toolRefsToCompletionTools(completionTools []ToolReference, prg Program) (re subToolName = subToolRef.Named } - args := subTool.Parameters.Arguments + args := subTool.Arguments if args == nil && !subTool.IsCommand() && !subTool.Chat { args = &system.DefaultToolSchema } else if args == nil && !subTool.IsCommand() { @@ -720,7 +817,7 @@ func toolRefsToCompletionTools(completionTools []ToolReference, prg Program) (re Function: CompletionFunctionDefinition{ ToolID: subTool.ID, Name: PickToolName(subToolName, toolNames), - Description: subTool.Parameters.Description, + Description: subTool.Description, Parameters: args, }, }) @@ -783,6 +880,14 @@ func (t Tool) IsDaemon() bool { return strings.HasPrefix(t.Instructions, DaemonPrefix) } +func (t Tool) IsMCP() bool { + return strings.HasPrefix(t.Instructions, MCPPrefix) +} + +func (t Tool) IsMCPInvoke() bool { + return strings.HasPrefix(t.Instructions, MCPInvokePrefix) +} + func (t Tool) IsOpenAPI() bool { return strings.HasPrefix(t.Instructions, OpenAPIPrefix) } @@ -795,6 +900,10 @@ func (t Tool) IsEcho() bool { return strings.HasPrefix(t.Instructions, EchoPrefix) } +func (t Tool) IsCall() bool { + return strings.HasPrefix(t.Instructions, CallPrefix) +} + func (t Tool) IsHTTP() bool { return strings.HasPrefix(t.Instructions, "#!http://") || strings.HasPrefix(t.Instructions, "#!https://") diff --git a/pkg/types/tool_test.go b/pkg/types/tool_test.go index e95c2248..ca5172cd 100644 --- a/pkg/types/tool_test.go +++ b/pkg/types/tool_test.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( @@ -6,7 +7,7 @@ import ( "github.com/hexops/autogold/v2" ) -func TestToolDef_String(t *testing.T) { +func TestToolDef_Print(t *testing.T) { tool := ToolDef{ Parameters: Parameters{ Name: "Tool Sample", @@ -73,6 +74,7 @@ Credential: Credential2 Share Credential: ExportCredential1 Share Credential: ExportCredential2 Chat: true +Meta Data: requirements.txt: requests=5 This is a sample instruction --- @@ -81,10 +83,7 @@ This is a sample instruction // blah blah some ugly JSON } ---- -!metadata:Tool Sample:requirements.txt -requests=5 -`).Equal(t, tool.String()) +`).Equal(t, tool.Print()) } // float32Ptr is used to return a pointer to a given float32 value @@ -96,3 +95,23 @@ func float32Ptr(f float32) *float32 { func boolPtr(b bool) *bool { return &b } + +func TestSplitArg(t *testing.T) { + prefix, arg := SplitArg("") + autogold.Expect([]string{"", ""}).Equal(t, []string{prefix, arg}) + + prefix, arg = SplitArg("toolName") + autogold.Expect([]string{"toolName", ""}).Equal(t, []string{prefix, arg}) + + prefix, arg = SplitArg("toolName as myAlias") + autogold.Expect([]string{"toolName", "as myAlias"}).Equal(t, []string{prefix, arg}) + + prefix, arg = SplitArg("toolName with value1 as arg1 and value2 as arg2") + autogold.Expect([]string{"toolName", "value1 as arg1 and value2 as arg2"}).Equal(t, []string{prefix, arg}) + + prefix, arg = SplitArg("toolName as myAlias with value1 as arg1 and value2 as arg2") + autogold.Expect([]string{"toolName", "value1 as arg1 and value2 as arg2"}).Equal(t, []string{prefix, arg}) + + prefix, arg = SplitArg("toolName with value1 as arg1 and value2 as arg2 as myAlias") + autogold.Expect([]string{"toolName", "value1 as arg1 and value2 as arg2 as myAlias"}).Equal(t, []string{prefix, arg}) +} diff --git a/pkg/types/toolname.go b/pkg/types/toolname.go index 622e9bb5..c43c2e80 100644 --- a/pkg/types/toolname.go +++ b/pkg/types/toolname.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( diff --git a/pkg/types/toolname_test.go b/pkg/types/toolname_test.go index fc7a66ab..0233baab 100644 --- a/pkg/types/toolname_test.go +++ b/pkg/types/toolname_test.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( diff --git a/pkg/types/toolstring.go b/pkg/types/toolstring.go index 086ad043..f9a69584 100644 --- a/pkg/types/toolstring.go +++ b/pkg/types/toolstring.go @@ -1,3 +1,4 @@ +//nolint:revive package types import ( @@ -44,15 +45,18 @@ func ToDisplayText(tool Tool, input string) string { } func ToSysDisplayString(id string, args map[string]string) (string, error) { + if suffix, ok := strings.CutPrefix(id, MCPInvokePrefix); ok { + return fmt.Sprintf("Invoking MCP `%s`", suffix), nil + } + switch id { case "sys.append": return fmt.Sprintf("Appending to file `%s`", args["filename"]), nil case "sys.download": if location := args["location"]; location != "" { return fmt.Sprintf("Downloading `%s` to `%s`", args["url"], location), nil - } else { - return fmt.Sprintf("Downloading `%s` to workspace", args["url"]), nil } + return fmt.Sprintf("Downloading `%s` to workspace", args["url"]), nil case "sys.exec": return fmt.Sprintf("Running `%s`", args["command"]), nil case "sys.find": diff --git a/static/fs.go b/static/fs.go index 88e5f4ec..aff200c1 100644 --- a/static/fs.go +++ b/static/fs.go @@ -1,9 +1,6 @@ package static -import ( - "embed" - _ "embed" -) +import "embed" //go:embed * ui/_nuxt/* var UI embed.FS diff --git a/tools/gendocs/main.go b/tools/gendocs/main.go index f931bbea..362ea17b 100644 --- a/tools/gendocs/main.go +++ b/tools/gendocs/main.go @@ -40,7 +40,7 @@ func main() { func filePrepender(filename string) string { name := filepath.Base(filename) base := strings.TrimSuffix(name, path.Ext(name)) - return fmt.Sprintf(fmTemplate, strings.Replace(base, "_", " ", -1)) + return fmt.Sprintf(fmTemplate, strings.ReplaceAll(base, "_", " ")) } func linkHandler(name string) string {