mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
Merge branch 'dev' into opentui
This commit is contained in:
commit
8b2ce5486d
285 changed files with 23552 additions and 528 deletions
71
.github/publish-python-sdk.yml
vendored
Normal file
71
.github/publish-python-sdk.yml
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# This file is intentionally in the wrong dir, will move and add later....
|
||||
#
|
||||
|
||||
# name: publish-python-sdk
|
||||
|
||||
# on:
|
||||
# release:
|
||||
# types: [published]
|
||||
# workflow_dispatch:
|
||||
|
||||
# jobs:
|
||||
# publish:
|
||||
# runs-on: ubuntu-latest
|
||||
# permissions:
|
||||
# contents: read
|
||||
# steps:
|
||||
# - name: Checkout repository
|
||||
# uses: actions/checkout@v4
|
||||
|
||||
# - name: Setup Bun
|
||||
# uses: oven-sh/setup-bun@v1
|
||||
# with:
|
||||
# bun-version: 1.2.21
|
||||
|
||||
# - name: Install dependencies (JS/Bun)
|
||||
# run: bun install
|
||||
|
||||
# - name: Install uv
|
||||
# shell: bash
|
||||
# run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# - name: Generate Python SDK from OpenAPI (CLI)
|
||||
# shell: bash
|
||||
# run: |
|
||||
# ~/.local/bin/uv run --project packages/sdk/python python packages/sdk/python/scripts/generate.py --source cli
|
||||
|
||||
# - name: Sync Python dependencies
|
||||
# shell: bash
|
||||
# run: |
|
||||
# ~/.local/bin/uv sync --dev --project packages/sdk/python
|
||||
|
||||
# - name: Set version from release tag
|
||||
# shell: bash
|
||||
# run: |
|
||||
# TAG="${GITHUB_REF_NAME:-}"
|
||||
# if [ -z "$TAG" ]; then
|
||||
# TAG="$(git describe --tags --abbrev=0 || echo 0.0.0)"
|
||||
# fi
|
||||
# echo "Using version: $TAG"
|
||||
# VERSION="$TAG" ~/.local/bin/uv run --project packages/sdk/python python - <<'PY'
|
||||
# import os, re, pathlib
|
||||
# root = pathlib.Path('packages/sdk/python')
|
||||
# pt = (root / 'pyproject.toml').read_text()
|
||||
# version = os.environ.get('VERSION','0.0.0').lstrip('v')
|
||||
# pt = re.sub(r'(?m)^(version\s*=\s*")[^"]+("\s*)$', f"\\1{version}\\2", pt)
|
||||
# (root / 'pyproject.toml').write_text(pt)
|
||||
# # Also update generator config override for consistency
|
||||
# cfgp = root / 'openapi-python-client.yaml'
|
||||
# if cfgp.exists():
|
||||
# cfg = cfgp.read_text()
|
||||
# cfg = re.sub(r'(?m)^(package_version_override:\s*)\S+$', f"\\1{version}", cfg)
|
||||
# cfgp.write_text(cfg)
|
||||
# PY
|
||||
|
||||
# - name: Build and publish to PyPI
|
||||
# env:
|
||||
# PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
||||
# shell: bash
|
||||
# run: |
|
||||
# ~/.local/bin/uv run --project packages/sdk/python python packages/sdk/python/scripts/publish.py
|
||||
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
|
|
@ -53,13 +53,17 @@ jobs:
|
|||
- name: Install OpenCode
|
||||
run: curl -fsSL https://opencode.ai/install | bash
|
||||
|
||||
- name: Setup npm auth
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
./script/publish.ts
|
||||
env:
|
||||
OPENCODE_BUMP: ${{ inputs.bump }}
|
||||
OPENCODE_CHANNEL: latest
|
||||
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||
AUR_KEY: ${{ secrets.AUR_KEY }}
|
||||
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
||||
|
|
|
|||
1
STATS.md
1
STATS.md
|
|
@ -122,3 +122,4 @@
|
|||
| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) |
|
||||
| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) |
|
||||
| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) |
|
||||
| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) |
|
||||
|
|
|
|||
88
bun.lock
88
bun.lock
|
|
@ -39,7 +39,7 @@
|
|||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "2.0.0",
|
||||
"@ai-sdk/openai": "2.0.2",
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
|
@ -111,12 +111,12 @@
|
|||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@pierre/precision-diffs": "0.3.5",
|
||||
"@pierre/precision-diffs": "catalog:",
|
||||
"@shikijs/transformers": "3.9.2",
|
||||
"@solid-primitives/active-element": "2.1.3",
|
||||
"@solid-primitives/event-bus": "1.1.2",
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "22.0.0",
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
|
|
@ -244,7 +244,7 @@
|
|||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"zod": "catalog:",
|
||||
|
|
@ -264,7 +264,7 @@
|
|||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.81.0",
|
||||
"@tsconfig/node22": "catalog:",
|
||||
|
|
@ -275,7 +275,7 @@
|
|||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
|
|
@ -288,7 +288,7 @@
|
|||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/precision-diffs": "catalog:",
|
||||
|
|
@ -311,7 +311,7 @@
|
|||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
|
|
@ -358,7 +358,7 @@
|
|||
"@hono/zod-validator": "0.4.2",
|
||||
"@kobalte/core": "0.13.11",
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@pierre/precision-diffs": "0.3.2",
|
||||
"@pierre/precision-diffs": "0.3.6",
|
||||
"@solidjs/meta": "0.29.4",
|
||||
"@tailwindcss/vite": "4.1.11",
|
||||
"@tsconfig/bun": "1.0.9",
|
||||
|
|
@ -1027,7 +1027,7 @@
|
|||
|
||||
"@petamoriken/float16": ["@petamoriken/float16@3.9.3", "", {}, "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g=="],
|
||||
|
||||
"@pierre/precision-diffs": ["@pierre/precision-diffs@0.3.5", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/transformers": "3.13.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.13.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-qbotIS8CahO/7guljDzU3RVpDfg6WViWe0EB0/SZQi3xHD+nzxxlC+pGoyIFSn+47GG0EKxTnvkfaYANm19FCA=="],
|
||||
"@pierre/precision-diffs": ["@pierre/precision-diffs@0.3.6", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/transformers": "3.13.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.13.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-cKM3HcMmyr5wPFll0bHYcgHplcHgMlL6Dw4Pi4giL0jVt7ySlGwwVyXTRFW5Fva43stOL+EWB+9U5VBDSktBJA=="],
|
||||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
|
|
@ -1113,7 +1113,7 @@
|
|||
|
||||
"@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="],
|
||||
|
||||
"@rollup/plugin-replace": ["@rollup/plugin-replace@6.0.2", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "magic-string": "^0.30.3" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ=="],
|
||||
"@rollup/plugin-replace": ["@rollup/plugin-replace@6.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "magic-string": "^0.30.3" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA=="],
|
||||
|
||||
"@rollup/plugin-terser": ["@rollup/plugin-terser@0.4.4", "", { "dependencies": { "serialize-javascript": "^6.0.1", "smob": "^1.0.0", "terser": "^5.17.4" }, "peerDependencies": { "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A=="],
|
||||
|
||||
|
|
@ -1441,7 +1441,7 @@
|
|||
|
||||
"@types/scheduler": ["@types/scheduler@0.26.0", "", {}, "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA=="],
|
||||
|
||||
"@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="],
|
||||
"@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
|
||||
|
||||
"@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="],
|
||||
|
||||
|
|
@ -1583,7 +1583,7 @@
|
|||
|
||||
"aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="],
|
||||
|
||||
"axios": ["axios@1.13.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-zt40Pz4zcRXra9CVV31KeyofwiNvAbJ5B6YPz9pMJ+yOSLikvPT4Yi5LjfgjRa9CawVYBaD1JQzIVcIvBejKeA=="],
|
||||
"axios": ["axios@1.13.1", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw=="],
|
||||
|
||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||
|
||||
|
|
@ -1617,7 +1617,7 @@
|
|||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.20", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ=="],
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.21", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q=="],
|
||||
|
||||
"bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="],
|
||||
|
||||
|
|
@ -1913,7 +1913,7 @@
|
|||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.241", "", {}, "sha512-ILMvKX/ZV5WIJzzdtuHg8xquk2y0BOGlFOxBVwTpbiXqWIH0hamG45ddU4R3PQ0gYu+xgo0vdHXHli9sHIGb4w=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.243", "", {}, "sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
|
|
@ -2703,7 +2703,7 @@
|
|||
|
||||
"no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="],
|
||||
|
||||
"node-abi": ["node-abi@3.78.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ=="],
|
||||
"node-abi": ["node-abi@3.79.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-Pr/5KdBQGG8TirdkS0qN3B+f3eo8zTOfZQWAxHoJqopMz2/uvRnG+S4fWu/6AZxKei2CP2p/psdQ5HFC2Ap5BA=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="],
|
||||
|
||||
|
|
@ -3137,7 +3137,7 @@
|
|||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
|
||||
"sitemap": ["sitemap@8.0.1", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.4.1" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-4Y8ynSMFAy/DadeAeio8Kx4zfC8/0VcKi7TH0I1SazvBcrU2fpJaGoeWsX1FMRaHoe3VGMA53DqVoLErZrtG9Q=="],
|
||||
"sitemap": ["sitemap@8.0.2", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.4.1" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ=="],
|
||||
|
||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
|
|
@ -3507,7 +3507,7 @@
|
|||
|
||||
"workerd": ["workerd@1.20251011.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251011.0", "@cloudflare/workerd-darwin-arm64": "1.20251011.0", "@cloudflare/workerd-linux-64": "1.20251011.0", "@cloudflare/workerd-linux-arm64": "1.20251011.0", "@cloudflare/workerd-windows-64": "1.20251011.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Dq35TLPEJAw7BuYQMkN3p9rge34zWMU2Gnd4DSJFeVqld4+DAO2aPG7+We2dNIAyM97S8Y9BmHulbQ00E0HC7Q=="],
|
||||
|
||||
"wrangler": ["wrangler@4.45.1", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.8", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251011.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.21", "workerd": "1.20251011.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251011.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-SmmbDl6NUkv6mHT8/Scb09lvxXy0Y2hD98oZHswCysrYbs4JW5LP1eTuroE23Z2jK75D7TEzv2MXmwcDIytxhg=="],
|
||||
"wrangler": ["wrangler@4.45.2", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.8", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251011.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.21", "workerd": "1.20251011.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251011.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-+G24gD+Rh7iBus5QiVBhNgSLzyAiyuZSm+3Ih5li8+PEA+gosAXfDSZlNZwsVmXd8VJTjq+BR4vhUiruQRWgTw=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||
|
||||
|
|
@ -3705,8 +3705,6 @@
|
|||
|
||||
"@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs": ["@pierre/precision-diffs@0.3.2", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/transformers": "3.13.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.13.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-HE+wFB0TV+wmjur/J+qI5PsRQl5RN6tCEFTusW0S5FDfZJUIpkxJCacqUxyEI0DriXMKhgGQ+oCQShfaFELdrQ=="],
|
||||
|
||||
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="],
|
||||
|
||||
"@opencode-ai/web/@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="],
|
||||
|
|
@ -3775,12 +3773,12 @@
|
|||
|
||||
"@tanstack/directive-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
|
||||
|
||||
"@tanstack/router-utils/@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="],
|
||||
|
||||
"@tanstack/router-utils/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"@tanstack/server-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
|
||||
|
||||
"@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
|
||||
|
||||
"@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"@vercel/nft/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
|
|
@ -3863,6 +3861,8 @@
|
|||
|
||||
"editorconfig/minimatch": ["minimatch@9.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w=="],
|
||||
|
||||
"editorconfig/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"es-get-iterator/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
|
||||
|
||||
"esbuild-plugin-copy/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||
|
|
@ -3959,14 +3959,14 @@
|
|||
|
||||
"nitropack/unenv": ["unenv@2.0.0-rc.23", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-NeOb/HbW2OwOzYaV21MewVQYfzlSwG0kVUB74RyV0gEIP44M5DsYTK9e7jDcekB/3YU+pfNWniZj+r4M/aejyQ=="],
|
||||
|
||||
"node-abi/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||
|
||||
"nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"nypm/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs": ["@pierre/precision-diffs@0.3.2", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/transformers": "3.13.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.13.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-HE+wFB0TV+wmjur/J+qI5PsRQl5RN6tCEFTusW0S5FDfZJUIpkxJCacqUxyEI0DriXMKhgGQ+oCQShfaFELdrQ=="],
|
||||
|
||||
"opencontrol/@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.6.1", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="],
|
||||
|
||||
"opencontrol/@tsconfig/bun": ["@tsconfig/bun@1.0.7", "", {}, "sha512-udGrGJBNQdXGVulehc1aWT73wkR9wdaGBtB6yL70RJsqwW/yJhIg6ZbRlPOfIUiFNrnBuYLBi9CSmMKfDC7dvA=="],
|
||||
|
|
@ -4325,10 +4325,6 @@
|
|||
|
||||
"@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@26.0.0", "", {}, "sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/@shikijs/transformers": ["@shikijs/transformers@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/types": "3.13.0" } }, "sha512-833lcuVzcRiG+fXvgslWsM2f4gHpjEgui1ipIknSizRuTgMkNZupiXE5/TVJ6eSYfhNBFhBZKkReKWO2GgYmqA=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki": ["shiki@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/engine-javascript": "3.13.0", "@shikijs/engine-oniguruma": "3.13.0", "@shikijs/langs": "3.13.0", "@shikijs/themes": "3.13.0", "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g=="],
|
||||
|
||||
"@opencode-ai/web/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ=="],
|
||||
|
||||
"@opencode-ai/web/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg=="],
|
||||
|
|
@ -4515,10 +4511,6 @@
|
|||
|
||||
"nypm/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/@shikijs/transformers": ["@shikijs/transformers@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/types": "3.13.0" } }, "sha512-833lcuVzcRiG+fXvgslWsM2f4gHpjEgui1ipIknSizRuTgMkNZupiXE5/TVJ6eSYfhNBFhBZKkReKWO2GgYmqA=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki": ["shiki@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/engine-javascript": "3.13.0", "@shikijs/engine-oniguruma": "3.13.0", "@shikijs/langs": "3.13.0", "@shikijs/themes": "3.13.0", "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g=="],
|
||||
|
||||
"opencontrol/@modelcontextprotocol/sdk/express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="],
|
||||
|
||||
"opencontrol/@modelcontextprotocol/sdk/pkce-challenge": ["pkce-challenge@4.1.0", "", {}, "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ=="],
|
||||
|
|
@ -4705,18 +4697,6 @@
|
|||
|
||||
"@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.13.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki/@shikijs/langs": ["@shikijs/langs@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki/@shikijs/themes": ["@shikijs/themes@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg=="],
|
||||
|
||||
"@opencode-ai/ui/@pierre/precision-diffs/shiki/@shikijs/types": ["@shikijs/types@3.13.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw=="],
|
||||
|
||||
"@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="],
|
||||
|
||||
"@vercel/nft/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
|
@ -4743,18 +4723,6 @@
|
|||
|
||||
"nitropack/serve-static/send/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.13.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki/@shikijs/langs": ["@shikijs/langs@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki/@shikijs/themes": ["@shikijs/themes@3.13.0", "", { "dependencies": { "@shikijs/types": "3.13.0" } }, "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg=="],
|
||||
|
||||
"opencode/@pierre/precision-diffs/shiki/@shikijs/types": ["@shikijs/types@3.13.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw=="],
|
||||
|
||||
"opencontrol/@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||
|
||||
"opencontrol/@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="],
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
"@tsconfig/bun": "1.0.9",
|
||||
"@cloudflare/workers-types": "4.20251008.0",
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@pierre/precision-diffs": "0.3.2",
|
||||
"@pierre/precision-diffs": "0.3.6",
|
||||
"@solidjs/meta": "0.29.4",
|
||||
"@tailwindcss/vite": "4.1.11",
|
||||
"diff": "8.0.2",
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
"license": "MIT",
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 120
|
||||
"printWidth": 100
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"esbuild",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
|
||||
"build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
|
||||
"start": "vinxi start",
|
||||
"version": "0.15.20"
|
||||
"version": "0.15.23"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export async function handler(
|
|||
})
|
||||
const zenData = ZenData.list()
|
||||
const modelInfo = validateModel(zenData, body.model)
|
||||
const providerInfo = selectProvider(zenData, modelInfo)
|
||||
const providerInfo = selectProvider(zenData, modelInfo, input.request.headers.get("x-real-ip") ?? "")
|
||||
const authInfo = await authenticate(modelInfo, providerInfo)
|
||||
validateBilling(modelInfo, authInfo)
|
||||
validateModelSettings(authInfo)
|
||||
|
|
@ -222,11 +222,15 @@ export async function handler(
|
|||
return { id: modelId, ...modelData }
|
||||
}
|
||||
|
||||
function selectProvider(zenData: ZenData, model: Awaited<ReturnType<typeof validateModel>>) {
|
||||
function selectProvider(zenData: ZenData, model: Awaited<ReturnType<typeof validateModel>>, ip: string) {
|
||||
const providers = model.providers
|
||||
.filter((provider) => !provider.disabled)
|
||||
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
|
||||
const provider = providers[Math.floor(Math.random() * providers.length)]
|
||||
|
||||
// Use last character of IP address to select a provider
|
||||
const lastChar = ip.charCodeAt(ip.length - 1) || 0
|
||||
const index = lastChar % providers.length
|
||||
const provider = providers[index]
|
||||
|
||||
if (!(provider.id in zenData.providers)) {
|
||||
throw new ModelError(`Provider ${provider.id} not supported`)
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ export async function GET(input: APIEvent) {
|
|||
object: "list",
|
||||
data: Object.entries(zenData.models)
|
||||
.filter(([id]) => !disabledModels.includes(id))
|
||||
.map(([id, model]) => ({
|
||||
id: `opencode/${id}`,
|
||||
.map(([id, _model]) => ({
|
||||
id,
|
||||
object: "model",
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
owned_by: "opencode",
|
||||
|
|
@ -50,7 +50,10 @@ export async function GET(input: APIEvent) {
|
|||
})
|
||||
.from(KeyTable)
|
||||
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
||||
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)))
|
||||
.leftJoin(
|
||||
ModelTable,
|
||||
and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)),
|
||||
)
|
||||
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
||||
.then((rows) => rows.map((row) => row.model)),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.svg" />
|
||||
<title>OpenCode</title>
|
||||
</head>
|
||||
<body class="overscroll-none select-none text-12-regular">
|
||||
<body class="antialiased overscroll-none select-none text-12-regular">
|
||||
<!-- <script> -->
|
||||
<!-- ;(function () { -->
|
||||
<!-- const savedTheme = localStorage.getItem("theme") || "opencode" -->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@pierre/precision-diffs": "0.3.5",
|
||||
"@pierre/precision-diffs": "catalog:",
|
||||
"@shikijs/transformers": "3.9.2",
|
||||
"@solid-primitives/active-element": "2.1.3",
|
||||
"@solid-primitives/event-bus": "1.1.2",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import type { Part, AssistantMessage, ReasoningPart, TextPart, ToolPart } from "@opencode-ai/sdk"
|
||||
import type { Tool } from "opencode/tool/tool"
|
||||
import type { ReadTool } from "opencode/tool/read"
|
||||
import type { Part, AssistantMessage, ReasoningPart, TextPart, ToolPart, Message } from "@opencode-ai/sdk"
|
||||
import { children, Component, createMemo, For, Match, Show, Switch, type JSX } from "solid-js"
|
||||
import { Dynamic } from "solid-js/web"
|
||||
import { Markdown } from "./markdown"
|
||||
import { Collapsible, Icon, IconProps } from "@opencode-ai/ui"
|
||||
import { Checkbox, Collapsible, Diff, Icon, IconProps } from "@opencode-ai/ui"
|
||||
import { getDirectory, getFilename } from "@/utils"
|
||||
import type { Tool } from "opencode/tool/tool"
|
||||
import type { ReadTool } from "opencode/tool/read"
|
||||
import type { ListTool } from "opencode/tool/ls"
|
||||
import type { GlobTool } from "opencode/tool/glob"
|
||||
import type { GrepTool } from "opencode/tool/grep"
|
||||
|
|
@ -14,41 +14,39 @@ import type { TaskTool } from "opencode/tool/task"
|
|||
import type { BashTool } from "opencode/tool/bash"
|
||||
import type { EditTool } from "opencode/tool/edit"
|
||||
import type { WriteTool } from "opencode/tool/write"
|
||||
import type { TodoWriteTool } from "opencode/tool/todo"
|
||||
import { DiffChanges } from "./diff-changes"
|
||||
|
||||
export function AssistantMessage(props: { message: AssistantMessage; parts: Part[] }) {
|
||||
const filteredParts = createMemo(() => {
|
||||
return props.parts?.filter((x) => {
|
||||
if (x.type === "reasoning") return false
|
||||
return x.type !== "tool" || x.tool !== "todoread"
|
||||
})
|
||||
})
|
||||
return (
|
||||
<div class="w-full flex flex-col items-start gap-4">
|
||||
<For each={props.parts}>
|
||||
{(part) => {
|
||||
const component = createMemo(() => PART_MAPPING[part.type as keyof typeof PART_MAPPING])
|
||||
return (
|
||||
<Show when={component()}>
|
||||
<Dynamic component={component()} part={part as any} message={props.message} />
|
||||
</Show>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<For each={filteredParts()}>{(part) => <Part part={part} message={props.message} />}</For>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Part(props: { part: Part; message: Message; readonly?: boolean }) {
|
||||
const component = createMemo(() => PART_MAPPING[props.part.type as keyof typeof PART_MAPPING])
|
||||
return (
|
||||
<Show when={component()}>
|
||||
<Dynamic component={component()} part={props.part as any} message={props.message} readonly={props.readonly} />
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
const PART_MAPPING = {
|
||||
text: TextPart,
|
||||
tool: ToolPart,
|
||||
reasoning: ReasoningPart,
|
||||
}
|
||||
|
||||
function ReasoningPart(props: { part: ReasoningPart; message: AssistantMessage }) {
|
||||
return null
|
||||
// return (
|
||||
// <Show when={props.part.text.trim()}>
|
||||
// <div>{props.part.text}</div>
|
||||
// </Show>
|
||||
// )
|
||||
}
|
||||
|
||||
function TextPart(props: { part: TextPart; message: AssistantMessage }) {
|
||||
function ReasoningPart(props: { part: ReasoningPart; message: Message }) {
|
||||
return (
|
||||
<Show when={props.part.text.trim()}>
|
||||
<Markdown text={props.part.text.trim()} />
|
||||
|
|
@ -56,30 +54,29 @@ function TextPart(props: { part: TextPart; message: AssistantMessage }) {
|
|||
)
|
||||
}
|
||||
|
||||
function ToolPart(props: { part: ToolPart; message: AssistantMessage }) {
|
||||
// const sync = useSync()
|
||||
function TextPart(props: { part: TextPart; message: Message }) {
|
||||
return (
|
||||
<Show when={props.part.text.trim()}>
|
||||
<Markdown text={props.part.text.trim()} />
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
function ToolPart(props: { part: ToolPart; message: Message; readonly?: boolean }) {
|
||||
const component = createMemo(() => {
|
||||
const render = ToolRegistry.render(props.part.tool) ?? GenericTool
|
||||
|
||||
const metadata = props.part.state.status === "pending" ? {} : (props.part.state.metadata ?? {})
|
||||
const input = props.part.state.status === "completed" ? props.part.state.input : {}
|
||||
// const permissions = sync.data.permission[props.message.sessionID] ?? []
|
||||
// const permissionIndex = permissions.findIndex((x) => x.callID === props.part.callID)
|
||||
// const permission = permissions[permissionIndex]
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dynamic
|
||||
component={render}
|
||||
input={input}
|
||||
tool={props.part.tool}
|
||||
metadata={metadata}
|
||||
// permission={permission?.metadata ?? {}}
|
||||
output={props.part.state.status === "completed" ? props.part.state.output : undefined}
|
||||
/>
|
||||
{/* <Show when={props.part.state.status === "error"}>{props.part.state.error.replace("Error: ", "")}</Show> */}
|
||||
</>
|
||||
<Dynamic
|
||||
component={render}
|
||||
input={input}
|
||||
tool={props.part.tool}
|
||||
metadata={metadata}
|
||||
output={props.part.state.status === "completed" ? props.part.state.output : undefined}
|
||||
readonly={props.readonly}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -88,8 +85,11 @@ function ToolPart(props: { part: ToolPart; message: AssistantMessage }) {
|
|||
|
||||
type TriggerTitle = {
|
||||
title: string
|
||||
titleClass?: string
|
||||
subtitle?: string
|
||||
subtitleClass?: string
|
||||
args?: string[]
|
||||
argsClass?: string
|
||||
action?: JSX.Element
|
||||
}
|
||||
|
||||
|
|
@ -97,59 +97,91 @@ const isTriggerTitle = (val: any): val is TriggerTitle => {
|
|||
return typeof val === "object" && val !== null && "title" in val && !(val instanceof Node)
|
||||
}
|
||||
|
||||
function BasicTool(props: { icon: IconProps["name"]; trigger: TriggerTitle | JSX.Element; children?: JSX.Element }) {
|
||||
function BasicTool(props: {
|
||||
icon: IconProps["name"]
|
||||
trigger: TriggerTitle | JSX.Element
|
||||
children?: JSX.Element
|
||||
readonly?: boolean
|
||||
}) {
|
||||
const resolved = children(() => props.children)
|
||||
|
||||
return (
|
||||
<Collapsible>
|
||||
<Collapsible.Trigger>
|
||||
<div class="w-full flex items-center self-stretch gap-5 justify-between">
|
||||
<div class="w-full flex items-center self-stretch gap-5">
|
||||
<Icon name={props.icon} size="small" />
|
||||
<Switch>
|
||||
<Match when={isTriggerTitle(props.trigger)}>
|
||||
<div class="w-full flex items-center gap-2 justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-12-medium text-text-base capitalize">
|
||||
{(props.trigger as TriggerTitle).title}
|
||||
</span>
|
||||
<Show when={(props.trigger as TriggerTitle).subtitle}>
|
||||
<span class="text-12-medium text-text-weak">{(props.trigger as TriggerTitle).subtitle}</span>
|
||||
</Show>
|
||||
<Show when={(props.trigger as TriggerTitle).args?.length}>
|
||||
<For each={(props.trigger as TriggerTitle).args}>
|
||||
{(arg) => <span class="text-12-regular text-text-weaker">{arg}</span>}
|
||||
</For>
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={(props.trigger as TriggerTitle).action}>{(props.trigger as TriggerTitle).action}</Show>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={true}>{props.trigger as JSX.Element}</Match>
|
||||
</Switch>
|
||||
<Icon name={props.icon} size="small" class="shrink-0" />
|
||||
<div class="grow min-w-0">
|
||||
<Switch>
|
||||
<Match when={isTriggerTitle(props.trigger) && props.trigger}>
|
||||
{(trigger) => (
|
||||
<div class="w-full flex items-center gap-2 justify-between">
|
||||
<div class="flex items-center gap-2 whitespace-nowrap truncate">
|
||||
<span
|
||||
classList={{
|
||||
"text-12-medium text-text-base": true,
|
||||
[trigger().titleClass ?? ""]: !!trigger().titleClass,
|
||||
}}
|
||||
>
|
||||
{trigger().title}
|
||||
</span>
|
||||
<Show when={trigger().subtitle}>
|
||||
<span
|
||||
classList={{
|
||||
"text-12-medium text-text-weak": true,
|
||||
[trigger().subtitleClass ?? ""]: !!trigger().subtitleClass,
|
||||
}}
|
||||
>
|
||||
{trigger().subtitle}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={trigger().args?.length}>
|
||||
<For each={trigger().args}>
|
||||
{(arg) => (
|
||||
<span
|
||||
classList={{
|
||||
"text-12-regular text-text-weak": true,
|
||||
[trigger().argsClass ?? ""]: !!trigger().argsClass,
|
||||
}}
|
||||
>
|
||||
{arg}
|
||||
</span>
|
||||
)}
|
||||
</For>
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={trigger().action}>{trigger().action}</Show>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={true}>{props.trigger as JSX.Element}</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={resolved()}>
|
||||
<Show when={resolved() && !props.readonly}>
|
||||
<Collapsible.Arrow />
|
||||
</Show>
|
||||
</div>
|
||||
</Collapsible.Trigger>
|
||||
<Show when={props.children}>
|
||||
<Collapsible.Content>{props.children}</Collapsible.Content>
|
||||
<Show when={resolved() && !props.readonly}>
|
||||
<Collapsible.Content>{resolved()}</Collapsible.Content>
|
||||
</Show>
|
||||
</Collapsible>
|
||||
// <>
|
||||
// <Show when={props.part.state.status === "error"}>{props.part.state.error.replace("Error: ", "")}</Show>
|
||||
// </>
|
||||
)
|
||||
}
|
||||
|
||||
function GenericTool(props: ToolProps<any>) {
|
||||
return <BasicTool icon="mcp" trigger={{ title: props.tool }} />
|
||||
return <BasicTool icon="mcp" trigger={{ title: props.tool }} readonly={props.readonly} />
|
||||
}
|
||||
|
||||
type ToolProps<T extends Tool.Info> = {
|
||||
input: Partial<Tool.InferParameters<T>>
|
||||
metadata: Partial<Tool.InferMetadata<T>>
|
||||
// permission: Record<string, any>
|
||||
tool: string
|
||||
output?: string
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
const ToolRegistry = (() => {
|
||||
|
|
@ -178,7 +210,7 @@ ToolRegistry.register<typeof ReadTool>({
|
|||
return (
|
||||
<BasicTool
|
||||
icon="glasses"
|
||||
trigger={{ title: props.tool, subtitle: props.input.filePath ? getFilename(props.input.filePath) : "" }}
|
||||
trigger={{ title: "Read", subtitle: props.input.filePath ? getFilename(props.input.filePath) : "" }}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
|
@ -188,7 +220,7 @@ ToolRegistry.register<typeof ListTool>({
|
|||
name: "list",
|
||||
render(props) {
|
||||
return (
|
||||
<BasicTool icon="bullet-list" trigger={{ title: props.tool, subtitle: props.input.path || "/" }}>
|
||||
<BasicTool icon="bullet-list" trigger={{ title: "List", subtitle: getDirectory(props.input.path || "/") }}>
|
||||
<Show when={false && props.output}>
|
||||
<div class="whitespace-pre">{props.output}</div>
|
||||
</Show>
|
||||
|
|
@ -204,8 +236,8 @@ ToolRegistry.register<typeof GlobTool>({
|
|||
<BasicTool
|
||||
icon="magnifying-glass-menu"
|
||||
trigger={{
|
||||
title: props.tool,
|
||||
subtitle: props.input.path || "/",
|
||||
title: "Glob",
|
||||
subtitle: getDirectory(props.input.path || "/"),
|
||||
args: props.input.pattern ? ["pattern=" + props.input.pattern] : [],
|
||||
}}
|
||||
>
|
||||
|
|
@ -227,8 +259,8 @@ ToolRegistry.register<typeof GrepTool>({
|
|||
<BasicTool
|
||||
icon="magnifying-glass-menu"
|
||||
trigger={{
|
||||
title: props.tool,
|
||||
subtitle: props.input.path || "/",
|
||||
title: "Grep",
|
||||
subtitle: getDirectory(props.input.path || "/"),
|
||||
args,
|
||||
}}
|
||||
>
|
||||
|
|
@ -247,7 +279,7 @@ ToolRegistry.register<typeof WebFetchTool>({
|
|||
<BasicTool
|
||||
icon="window-cursor"
|
||||
trigger={{
|
||||
title: props.tool,
|
||||
title: "Webfetch",
|
||||
subtitle: props.input.url || "",
|
||||
args: props.input.format ? ["format=" + props.input.format] : [],
|
||||
action: (
|
||||
|
|
@ -273,6 +305,7 @@ ToolRegistry.register<typeof TaskTool>({
|
|||
icon="task"
|
||||
trigger={{
|
||||
title: `${props.input.subagent_type || props.tool} Agent`,
|
||||
titleClass: "capitalize",
|
||||
subtitle: props.input.description,
|
||||
}}
|
||||
>
|
||||
|
|
@ -311,11 +344,49 @@ ToolRegistry.register<typeof EditTool>({
|
|||
icon="code-lines"
|
||||
trigger={
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="text-12-medium text-text-base capitalize">Edit</div>
|
||||
<div class="flex">
|
||||
<Show when={props.input.filePath?.includes("/")}>
|
||||
<span class="text-text-weak">{getDirectory(props.input.filePath!)}/</span>
|
||||
<span class="text-text-weak">{getDirectory(props.input.filePath!)}</span>
|
||||
</Show>
|
||||
<span class="text-text-strong">{getFilename(props.input.filePath ?? "")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 items-center justify-end">
|
||||
<Show when={props.metadata.filediff}>
|
||||
<DiffChanges diff={props.metadata.filediff} />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Show when={props.metadata.filediff}>
|
||||
<div class="border-t border-border-weaker-base">
|
||||
<Diff
|
||||
before={{ name: getFilename(props.metadata.filediff.path), contents: props.metadata.filediff.before }}
|
||||
after={{ name: getFilename(props.metadata.filediff.path), contents: props.metadata.filediff.after }}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
ToolRegistry.register<typeof WriteTool>({
|
||||
name: "write",
|
||||
render(props) {
|
||||
return (
|
||||
<BasicTool
|
||||
icon="code-lines"
|
||||
trigger={
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="text-12-medium text-text-base capitalize">Write</div>
|
||||
<div class="flex">
|
||||
<Show when={props.input.filePath?.includes("/")}>
|
||||
<span class="text-text-weak">{getDirectory(props.input.filePath!)}</span>
|
||||
</Show>
|
||||
<span class="text-text-strong">{getFilename(props.input.filePath ?? "")}</span>
|
||||
</div>
|
||||
|
|
@ -332,29 +403,27 @@ ToolRegistry.register<typeof EditTool>({
|
|||
},
|
||||
})
|
||||
|
||||
ToolRegistry.register<typeof WriteTool>({
|
||||
name: "write",
|
||||
ToolRegistry.register<typeof TodoWriteTool>({
|
||||
name: "todowrite",
|
||||
render(props) {
|
||||
return (
|
||||
<BasicTool
|
||||
icon="code-lines"
|
||||
trigger={
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="text-12-medium text-text-base capitalize">Write</div>
|
||||
<div class="flex">
|
||||
<Show when={props.input.filePath?.includes("/")}>
|
||||
<span class="text-text-weak">{getDirectory(props.input.filePath!)}/</span>
|
||||
</Show>
|
||||
<span class="text-text-strong">{getFilename(props.input.filePath ?? "")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 items-center justify-end">{/* <DiffChanges diff={diff} /> */}</div>
|
||||
</div>
|
||||
}
|
||||
icon="checklist"
|
||||
trigger={{
|
||||
title: "To-dos",
|
||||
subtitle: `${props.input.todos?.filter((t) => t.status === "completed").length}/${props.input.todos?.length}`,
|
||||
}}
|
||||
>
|
||||
<Show when={false && props.output}>
|
||||
<div class="whitespace-pre">{props.output}</div>
|
||||
<Show when={props.input.todos?.length}>
|
||||
<div class="px-12 pt-2.5 pb-6 flex flex-col gap-2">
|
||||
<For each={props.input.todos}>
|
||||
{(todo) => (
|
||||
<Checkbox readOnly checked={todo.status === "completed"}>
|
||||
<div classList={{ "line-through text-text-weaker": todo.status === "completed" }}>{todo.content}</div>
|
||||
</Checkbox>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</BasicTool>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@ import { DateTime } from "luxon"
|
|||
|
||||
interface PartBase {
|
||||
content: string
|
||||
start: number
|
||||
end: number
|
||||
}
|
||||
|
||||
interface TextPart extends PartBase {
|
||||
export interface TextPart extends PartBase {
|
||||
type: "text"
|
||||
}
|
||||
|
||||
interface FileAttachmentPart extends PartBase {
|
||||
export interface FileAttachmentPart extends PartBase {
|
||||
type: "file"
|
||||
path: string
|
||||
selection?: TextSelection
|
||||
|
|
@ -34,7 +36,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
const local = useLocal()
|
||||
let editorRef!: HTMLDivElement
|
||||
|
||||
const defaultParts = [{ type: "text", content: "" } as const]
|
||||
const defaultParts = [{ type: "text", content: "", start: 0, end: 0 } as const]
|
||||
const [store, setStore] = createStore<{
|
||||
contentParts: ContentPart[]
|
||||
popoverIsOpen: boolean
|
||||
|
|
@ -51,7 +53,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
event.stopPropagation()
|
||||
// @ts-expect-error
|
||||
const plainText = (event.clipboardData || window.clipboardData)?.getData("text/plain") ?? ""
|
||||
addPart({ type: "text", content: plainText })
|
||||
addPart({ type: "text", content: plainText, start: 0, end: 0 })
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
|
@ -74,7 +76,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
key: (x) => x,
|
||||
onSelect: (path) => {
|
||||
if (!path) return
|
||||
addPart({ type: "file", path, content: "@" + getFilename(path) })
|
||||
addPart({ type: "file", path, content: "@" + getFilename(path), start: 0, end: 0 })
|
||||
setStore("popoverIsOpen", false)
|
||||
},
|
||||
})
|
||||
|
|
@ -117,17 +119,26 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
|
||||
const parseFromDOM = (): ContentPart[] => {
|
||||
const newParts: ContentPart[] = []
|
||||
let position = 0
|
||||
editorRef.childNodes.forEach((node) => {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
if (node.textContent) newParts.push({ type: "text", content: node.textContent })
|
||||
if (node.textContent) {
|
||||
const content = node.textContent
|
||||
newParts.push({ type: "text", content, start: position, end: position + content.length })
|
||||
position += content.length
|
||||
}
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).dataset.type) {
|
||||
switch ((node as HTMLElement).dataset.type) {
|
||||
case "file":
|
||||
const content = node.textContent!
|
||||
newParts.push({
|
||||
type: "file",
|
||||
path: (node as HTMLElement).dataset.path!,
|
||||
content: node.textContent!,
|
||||
content,
|
||||
start: position,
|
||||
end: position + content.length,
|
||||
})
|
||||
position += content.length
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
|
@ -163,17 +174,19 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
const startIndex = atMatch ? atMatch.index! : cursorPosition
|
||||
const endIndex = atMatch ? cursorPosition : cursorPosition
|
||||
|
||||
const pushText = (acc: { parts: ContentPart[] }, value: string) => {
|
||||
const pushText = (acc: { parts: ContentPart[]; runningIndex: number }, value: string) => {
|
||||
if (!value) return
|
||||
const last = acc.parts[acc.parts.length - 1]
|
||||
if (last && last.type === "text") {
|
||||
acc.parts[acc.parts.length - 1] = {
|
||||
type: "text",
|
||||
content: last.content + value,
|
||||
start: last.start,
|
||||
end: last.end + value.length,
|
||||
}
|
||||
return
|
||||
}
|
||||
acc.parts.push({ type: "text", content: value })
|
||||
acc.parts.push({ type: "text", content: value, start: acc.runningIndex, end: acc.runningIndex + value.length })
|
||||
}
|
||||
|
||||
const {
|
||||
|
|
@ -183,20 +196,20 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
} = store.contentParts.reduce(
|
||||
(acc, item) => {
|
||||
if (acc.inserted) {
|
||||
acc.parts.push(item)
|
||||
acc.parts.push({ ...item, start: acc.runningIndex, end: acc.runningIndex + item.content.length })
|
||||
acc.runningIndex += item.content.length
|
||||
return acc
|
||||
}
|
||||
|
||||
const nextIndex = acc.runningIndex + item.content.length
|
||||
if (nextIndex <= startIndex) {
|
||||
acc.parts.push(item)
|
||||
acc.parts.push({ ...item, start: acc.runningIndex, end: acc.runningIndex + item.content.length })
|
||||
acc.runningIndex = nextIndex
|
||||
return acc
|
||||
}
|
||||
|
||||
if (item.type !== "text") {
|
||||
acc.parts.push(item)
|
||||
acc.parts.push({ ...item, start: acc.runningIndex, end: acc.runningIndex + item.content.length })
|
||||
acc.runningIndex = nextIndex
|
||||
return acc
|
||||
}
|
||||
|
|
@ -207,24 +220,27 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
const tail = item.content.slice(tailLength)
|
||||
|
||||
pushText(acc, head)
|
||||
acc.runningIndex += head.length
|
||||
|
||||
if (part.type === "text") {
|
||||
pushText(acc, part.content)
|
||||
acc.runningIndex += part.content.length
|
||||
}
|
||||
if (part.type !== "text") {
|
||||
acc.parts.push({ ...part })
|
||||
acc.parts.push({ ...part, start: acc.runningIndex, end: acc.runningIndex + part.content.length })
|
||||
acc.runningIndex += part.content.length
|
||||
}
|
||||
|
||||
const needsGap = Boolean(atMatch)
|
||||
const rest = needsGap ? (tail ? (/^\s/.test(tail) ? tail : ` ${tail}`) : " ") : tail
|
||||
pushText(acc, rest)
|
||||
acc.runningIndex += rest.length
|
||||
|
||||
const baseCursor = startIndex + part.content.length
|
||||
const cursorAddition = needsGap && rest.length > 0 ? 1 : 0
|
||||
acc.cursorPositionAfter = baseCursor + cursorAddition
|
||||
|
||||
acc.inserted = true
|
||||
acc.runningIndex = nextIndex
|
||||
return acc
|
||||
},
|
||||
{
|
||||
|
|
@ -237,9 +253,18 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
|
||||
if (!inserted) {
|
||||
const baseParts = store.contentParts.filter((item) => !(item.type === "text" && item.content === ""))
|
||||
const appendedAcc = { parts: [...baseParts] as ContentPart[] }
|
||||
if (part.type === "text") pushText(appendedAcc, part.content)
|
||||
if (part.type !== "text") appendedAcc.parts.push({ ...part })
|
||||
const runningIndex = baseParts.reduce((sum, p) => sum + p.content.length, 0)
|
||||
const appendedAcc = { parts: [...baseParts] as ContentPart[], runningIndex }
|
||||
if (part.type === "text") {
|
||||
pushText(appendedAcc, part.content)
|
||||
}
|
||||
if (part.type !== "text") {
|
||||
appendedAcc.parts.push({
|
||||
...part,
|
||||
start: appendedAcc.runningIndex,
|
||||
end: appendedAcc.runningIndex + part.content.length,
|
||||
})
|
||||
}
|
||||
const next = appendedAcc.parts.length > 0 ? appendedAcc.parts : defaultParts
|
||||
setStore("contentParts", next)
|
||||
setStore("popoverIsOpen", false)
|
||||
|
|
@ -289,7 +314,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
<FileIcon node={{ path: i, type: "file" }} class="shrink-0 size-4" />
|
||||
<div class="flex items-center text-14-regular">
|
||||
<span class="text-text-weak whitespace-nowrap overflow-hidden overflow-ellipsis truncate min-w-0">
|
||||
{getDirectory(i)}/
|
||||
{getDirectory(i)}
|
||||
</span>
|
||||
<span class="text-text-strong whitespace-nowrap">{getFilename(i)}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -429,13 +429,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
.sort((a, b) => b.id.localeCompare(a.id)),
|
||||
)
|
||||
|
||||
const working = createMemo(() => {
|
||||
const last = messages()[messages().length - 1]
|
||||
if (!last) return false
|
||||
if (last.role === "user") return true
|
||||
return !last.time.completed
|
||||
})
|
||||
|
||||
const cost = createMemo(() => {
|
||||
const total = pipe(
|
||||
messages(),
|
||||
|
|
@ -487,6 +480,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
const getMessageText = (message: Message | Message[] | undefined): string => {
|
||||
if (!message) return ""
|
||||
if (Array.isArray(message)) return message.map((m) => getMessageText(m)).join(" ")
|
||||
const fileParts = sync.data.part[message.id]?.filter((p) => p.type === "file")
|
||||
console.log(fileParts)
|
||||
|
||||
return sync.data.part[message.id]
|
||||
?.filter((p) => p.type === "text")
|
||||
?.filter((p) => !p.synthetic)
|
||||
|
|
@ -506,7 +502,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
messages,
|
||||
messagesWithValidParts,
|
||||
userMessages,
|
||||
working,
|
||||
// working,
|
||||
getMessageText,
|
||||
setActive(sessionId: string | undefined) {
|
||||
setStore("active", sessionId)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,19 @@
|
|||
import { Button, List, SelectDialog, Tooltip, IconButton, Tabs, Icon, Accordion } from "@opencode-ai/ui"
|
||||
import {
|
||||
Button,
|
||||
List,
|
||||
SelectDialog,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
Tabs,
|
||||
Icon,
|
||||
Accordion,
|
||||
Diff,
|
||||
Collapsible,
|
||||
} from "@opencode-ai/ui"
|
||||
import { FileIcon } from "@/ui"
|
||||
import FileTree from "@/components/file-tree"
|
||||
import { For, onCleanup, onMount, Show, Match, Switch, createSignal, createEffect, createMemo } from "solid-js"
|
||||
import { useLocal, type LocalFile, type TextSelection } from "@/context/local"
|
||||
import { useLocal, type LocalFile } from "@/context/local"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { getDirectory, getFilename } from "@/utils"
|
||||
import { ContentPart, PromptInput } from "@/components/prompt-input"
|
||||
|
|
@ -21,9 +32,8 @@ import type { JSX } from "solid-js"
|
|||
import { Code } from "@/components/code"
|
||||
import { useSync } from "@/context/sync"
|
||||
import { useSDK } from "@/context/sdk"
|
||||
import { Diff } from "@/components/diff"
|
||||
import { ProgressCircle } from "@/components/progress-circle"
|
||||
import { AssistantMessage } from "@/components/assistant-message"
|
||||
import { AssistantMessage, Part } from "@/components/assistant-message"
|
||||
import { type AssistantMessage as AssistantMessageType } from "@opencode-ai/sdk"
|
||||
import { DiffChanges } from "@/components/diff-changes"
|
||||
|
||||
|
|
@ -168,6 +178,8 @@ export default function Page() {
|
|||
}
|
||||
|
||||
const handleDiffTriggerClick = (event: MouseEvent) => {
|
||||
// disabling scroll to diff for now
|
||||
return
|
||||
const target = event.currentTarget as HTMLElement
|
||||
queueMicrotask(() => {
|
||||
if (target.getAttribute("aria-expanded") !== "true") return
|
||||
|
|
@ -186,42 +198,10 @@ export default function Page() {
|
|||
}
|
||||
if (!session) return
|
||||
|
||||
interface SubmissionAttachment {
|
||||
path: string
|
||||
selection?: TextSelection
|
||||
label: string
|
||||
}
|
||||
|
||||
const createAttachmentKey = (path: string, selection?: TextSelection) => {
|
||||
if (!selection) return path
|
||||
return `${path}:${selection.startLine}:${selection.startChar}:${selection.endLine}:${selection.endChar}`
|
||||
}
|
||||
|
||||
const formatAttachmentLabel = (path: string, selection?: TextSelection) => {
|
||||
if (!selection) return getFilename(path)
|
||||
return `${getFilename(path)} (${selection.startLine}-${selection.endLine})`
|
||||
}
|
||||
|
||||
const toAbsolutePath = (path: string) => (path.startsWith("/") ? path : sync.absolute(path))
|
||||
|
||||
const text = parts.map((part) => part.content).join("")
|
||||
const attachments = new Map<string, SubmissionAttachment>()
|
||||
|
||||
const registerAttachment = (path: string, selection: TextSelection | undefined, label?: string) => {
|
||||
if (!path) return
|
||||
const key = createAttachmentKey(path, selection)
|
||||
if (attachments.has(key)) return
|
||||
attachments.set(key, {
|
||||
path,
|
||||
selection,
|
||||
label: label ?? formatAttachmentLabel(path, selection),
|
||||
})
|
||||
}
|
||||
|
||||
const promptAttachments = parts.filter((part) => part.type === "file")
|
||||
for (const part of promptAttachments) {
|
||||
registerAttachment(part.path, part.selection, part.content)
|
||||
}
|
||||
const attachments = parts.filter((part) => part.type === "file")
|
||||
|
||||
// const activeFile = local.context.active()
|
||||
// if (activeFile) {
|
||||
|
|
@ -240,7 +220,7 @@ export default function Page() {
|
|||
// )
|
||||
// }
|
||||
|
||||
const attachmentParts = Array.from(attachments.values()).map((attachment) => {
|
||||
const attachmentParts = attachments.map((attachment) => {
|
||||
const absolute = toAbsolutePath(attachment.path)
|
||||
const query = attachment.selection
|
||||
? `?start=${attachment.selection.startLine}&end=${attachment.selection.endLine}`
|
||||
|
|
@ -253,9 +233,9 @@ export default function Page() {
|
|||
source: {
|
||||
type: "file" as const,
|
||||
text: {
|
||||
value: `@${attachment.label}`,
|
||||
start: 0,
|
||||
end: 0,
|
||||
value: attachment.content,
|
||||
start: attachment.start,
|
||||
end: attachment.end,
|
||||
},
|
||||
path: absolute,
|
||||
},
|
||||
|
|
@ -511,8 +491,8 @@ export default function Page() {
|
|||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<Tabs.Content value="chat" class="select-text flex flex-col flex-1 min-h-0">
|
||||
<div class="p-6 pt-12 max-w-[904px] w-full mx-auto flex flex-col flex-1 min-h-0">
|
||||
<Tabs.Content value="chat" class="select-text flex flex-col flex-1 min-h-0 overflow-y-hidden">
|
||||
<div class="px-6 pt-12 max-w-[904px] w-full mx-auto flex flex-col flex-1 min-h-0">
|
||||
<Show
|
||||
when={local.session.active()}
|
||||
fallback={
|
||||
|
|
@ -521,7 +501,7 @@ export default function Page() {
|
|||
<div class="flex justify-center items-center gap-3">
|
||||
<Icon name="folder" size="small" />
|
||||
<div class="text-12-medium text-text-weak">
|
||||
{getDirectory(sync.data.path.directory)}/
|
||||
{getDirectory(sync.data.path.directory)}
|
||||
<span class="text-text-strong">{getFilename(sync.data.path.directory)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -538,7 +518,7 @@ export default function Page() {
|
|||
}
|
||||
>
|
||||
{(activeSession) => (
|
||||
<div class="py-3 flex flex-col flex-1 min-h-0">
|
||||
<div class="pt-3 flex flex-col flex-1 min-h-0">
|
||||
<div class="flex items-start gap-8 flex-1 min-h-0">
|
||||
<Show when={local.session.userMessages().length > 1}>
|
||||
<ul role="list" class="w-60 shrink-0 flex flex-col items-start gap-1">
|
||||
|
|
@ -655,9 +635,10 @@ export default function Page() {
|
|||
</ul>
|
||||
</Show>
|
||||
<div ref={messageScrollElement} class="grow min-w-0 h-full overflow-y-auto no-scrollbar">
|
||||
<div class="flex flex-col items-start gap-50 pb-[800px]">
|
||||
<div class="flex flex-col items-start gap-50 pb-50">
|
||||
<For each={local.session.userMessages()}>
|
||||
{(message) => {
|
||||
const [expanded, setExpanded] = createSignal(false)
|
||||
const title = createMemo(() => message.summary?.title)
|
||||
const prompt = createMemo(() => local.session.getMessageText(message))
|
||||
const summary = createMemo(() => message.summary?.body)
|
||||
|
|
@ -666,54 +647,143 @@ export default function Page() {
|
|||
(m) => m.role === "assistant" && m.parentID == message.id,
|
||||
) as AssistantMessageType[]
|
||||
})
|
||||
const working = createMemo(() => {
|
||||
const last = assistantMessages()[assistantMessages().length - 1]
|
||||
if (!last) return false
|
||||
return !last.time.completed
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
data-message={message.id}
|
||||
class="flex flex-col items-start self-stretch gap-14 pt-1.5"
|
||||
class="flex flex-col items-start self-stretch gap-8 min-h-[calc(100vh-15rem)]"
|
||||
>
|
||||
{/* Title */}
|
||||
<div class="flex flex-col items-start gap-2 self-stretch">
|
||||
<div class="py-2 flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger">
|
||||
<h1 class="text-14-medium text-text-strong overflow-hidden text-ellipsis min-w-0">
|
||||
{title() ?? prompt()}
|
||||
</h1>
|
||||
<Show when={title}>
|
||||
<div class="text-12-regular text-text-base">{prompt()}</div>
|
||||
</div>
|
||||
<Show when={title}>
|
||||
<div class="-mt-8 text-12-regular text-text-base line-clamp-3">{prompt()}</div>
|
||||
</Show>
|
||||
{/* Response */}
|
||||
<div class="w-full flex flex-col gap-2">
|
||||
<Collapsible variant="ghost" open={expanded()} onOpenChange={setExpanded}>
|
||||
<Collapsible.Trigger class="text-text-weak hover:text-text-strong">
|
||||
<div class="flex items-center gap-1 self-stretch">
|
||||
<h2 class="text-12-medium">
|
||||
<Switch>
|
||||
<Match when={expanded()}>Hide steps</Match>
|
||||
<Match when={!expanded()}>Show steps</Match>
|
||||
</Switch>
|
||||
</h2>
|
||||
<Collapsible.Arrow />
|
||||
</div>
|
||||
</Collapsible.Trigger>
|
||||
<Collapsible.Content>
|
||||
<div class="w-full flex flex-col items-start self-stretch gap-8">
|
||||
<For each={assistantMessages()}>
|
||||
{(assistantMessage) => {
|
||||
const parts = createMemo(() => sync.data.part[assistantMessage.id])
|
||||
return <AssistantMessage message={assistantMessage} parts={parts()} />
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</Collapsible.Content>
|
||||
</Collapsible>
|
||||
<Show when={working() && !expanded()}>
|
||||
{(_) => {
|
||||
const lastMessageWithText = createMemo(() =>
|
||||
assistantMessages().findLast((m) => {
|
||||
const parts = sync.data.part[m.id]
|
||||
return parts?.find((p) => p.type === "text")
|
||||
}),
|
||||
)
|
||||
const lastMessageWithReasoning = createMemo(() =>
|
||||
assistantMessages().findLast((m) => {
|
||||
const parts = sync.data.part[m.id]
|
||||
return parts?.find((p) => p.type === "reasoning")
|
||||
}),
|
||||
)
|
||||
const lastMessageWithTool = createMemo(() =>
|
||||
assistantMessages().findLast((m) => {
|
||||
const parts = sync.data.part[m.id]
|
||||
return parts?.find(
|
||||
(p) => p.type === "tool" && p.state.status === "completed",
|
||||
)
|
||||
}),
|
||||
)
|
||||
return (
|
||||
<div class="w-full flex flex-col gap-2">
|
||||
<Switch>
|
||||
<Match when={lastMessageWithText()}>
|
||||
{(last) => {
|
||||
const lastTextPart = createMemo(() =>
|
||||
sync.data.part[last().id].findLast((p) => p.type === "text"),
|
||||
)
|
||||
return <Part message={last()} part={lastTextPart()!} readonly />
|
||||
}}
|
||||
</Match>
|
||||
<Match when={lastMessageWithReasoning()}>
|
||||
{(last) => {
|
||||
const lastReasoningPart = createMemo(() =>
|
||||
sync.data.part[last().id].findLast(
|
||||
(p) => p.type === "reasoning",
|
||||
),
|
||||
)
|
||||
return (
|
||||
<Part message={last()} part={lastReasoningPart()!} readonly />
|
||||
)
|
||||
}}
|
||||
</Match>
|
||||
</Switch>
|
||||
<Show when={lastMessageWithTool()}>
|
||||
{(last) => {
|
||||
const lastToolPart = createMemo(() =>
|
||||
sync.data.part[last().id].findLast(
|
||||
(p) => p.type === "tool" && p.state.status === "completed",
|
||||
),
|
||||
)
|
||||
return <Part message={last()} part={lastToolPart()!} readonly />
|
||||
}}
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</Show>
|
||||
</div>
|
||||
{/* Summary */}
|
||||
<div class="w-full flex flex-col gap-6 items-start self-stretch">
|
||||
<Show when={summary}>
|
||||
<Show when={!working()}>
|
||||
<div class="w-full flex flex-col gap-6 items-start self-stretch">
|
||||
<div class="flex flex-col items-start gap-1 self-stretch">
|
||||
<h2 class="text-12-medium text-text-weak">Summary</h2>
|
||||
<div class="text-14-regular text-text-base self-stretch">{summary()}</div>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={message.summary?.diffs.length}>
|
||||
<Accordion class="w-full" multiple>
|
||||
<For each={message.summary?.diffs || []}>
|
||||
{(diff) => (
|
||||
<Accordion.Item value={diff.file}>
|
||||
<Accordion.Header>
|
||||
<Accordion.Trigger onClick={handleDiffTriggerClick}>
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center justify-between w-full gap-5">
|
||||
<div class="grow flex items-center gap-5 min-w-0">
|
||||
<FileIcon
|
||||
node={{ path: diff.file, type: "file" }}
|
||||
class="shrink-0 size-4"
|
||||
/>
|
||||
<div class="flex">
|
||||
<div class="flex grow min-w-0">
|
||||
<Show when={diff.file.includes("/")}>
|
||||
<span class="text-text-base">
|
||||
{getDirectory(diff.file)}/
|
||||
<span class="text-text-base truncate-start">
|
||||
{getDirectory(diff.file)}‎
|
||||
</span>
|
||||
</Show>
|
||||
<span class="text-text-strong">
|
||||
<span class="text-text-strong shrink-0">
|
||||
{getFilename(diff.file)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 items-center justify-end">
|
||||
<div class="shrink-0 flex gap-4 items-center justify-end">
|
||||
<DiffChanges diff={diff} />
|
||||
<Icon name="chevron-grabber-vertical" size="small" />
|
||||
</div>
|
||||
|
|
@ -736,22 +806,8 @@ export default function Page() {
|
|||
)}
|
||||
</For>
|
||||
</Accordion>
|
||||
</Show>
|
||||
</div>
|
||||
{/* Response */}
|
||||
<div data-todo="Response" class="w-full">
|
||||
<div class="flex flex-col items-start gap-1 self-stretch">
|
||||
<h2 class="text-12-medium text-text-weak">Response</h2>
|
||||
</div>
|
||||
<div class="w-full flex flex-col items-start self-stretch gap-8">
|
||||
<For each={assistantMessages()}>
|
||||
{(assistantMessage) => {
|
||||
const parts = createMemo(() => sync.data.part[assistantMessage.id])
|
||||
return <AssistantMessage message={assistantMessage} parts={parts()} />
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
|
|
@ -858,7 +914,7 @@ export default function Page() {
|
|||
<FileIcon node={{ path: i, type: "file" }} class="shrink-0 size-4" />
|
||||
<div class="flex items-center text-14-regular">
|
||||
<span class="text-text-weak whitespace-nowrap overflow-hidden overflow-ellipsis truncate min-w-0">
|
||||
{getDirectory(i)}/
|
||||
{getDirectory(i)}
|
||||
</span>
|
||||
<span class="text-text-strong whitespace-nowrap">{getFilename(i)}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { useSync } from "@/context/sync"
|
||||
|
||||
export function getFilename(path: string) {
|
||||
if (!path) return ""
|
||||
const trimmed = path.replace(/[\/]+$/, "")
|
||||
|
|
@ -6,8 +8,10 @@ export function getFilename(path: string) {
|
|||
}
|
||||
|
||||
export function getDirectory(path: string) {
|
||||
const sync = useSync()
|
||||
const parts = path.split("/")
|
||||
return parts.slice(0, parts.length - 1).join("/")
|
||||
const dir = parts.slice(0, parts.length - 1).join("/")
|
||||
return dir ? sync.sanitize(dir + "/") : ""
|
||||
}
|
||||
|
||||
export function getFileExtension(path: string) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
|
|
|
|||
|
|
@ -40,16 +40,33 @@ for (const [name] of Object.entries(binaries)) {
|
|||
}
|
||||
await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.channel}`
|
||||
|
||||
if (!Script.preview) {
|
||||
const major = Script.version.split(".")[0]
|
||||
const majorTag = `latest-${major}`
|
||||
for (const [name] of Object.entries(binaries)) {
|
||||
await $`cd dist/${name} && npm dist-tag add ${name}@${Script.version} ${majorTag}`
|
||||
}
|
||||
await $`cd ./dist/${pkg.name} && npm dist-tag add ${pkg.name}-ai@${Script.version} ${majorTag}`
|
||||
}
|
||||
|
||||
if (!Script.preview) {
|
||||
for (const key of Object.keys(binaries)) {
|
||||
await $`cd dist/${key}/bin && zip -r ../../${key}.zip *`
|
||||
}
|
||||
|
||||
// Calculate SHA values
|
||||
const arm64Sha = await $`sha256sum ./dist/opencode-linux-arm64.zip | cut -d' ' -f1`.text().then((x) => x.trim())
|
||||
const x64Sha = await $`sha256sum ./dist/opencode-linux-x64.zip | cut -d' ' -f1`.text().then((x) => x.trim())
|
||||
const macX64Sha = await $`sha256sum ./dist/opencode-darwin-x64.zip | cut -d' ' -f1`.text().then((x) => x.trim())
|
||||
const macArm64Sha = await $`sha256sum ./dist/opencode-darwin-arm64.zip | cut -d' ' -f1`.text().then((x) => x.trim())
|
||||
const arm64Sha = await $`sha256sum ./dist/opencode-linux-arm64.zip | cut -d' ' -f1`
|
||||
.text()
|
||||
.then((x) => x.trim())
|
||||
const x64Sha = await $`sha256sum ./dist/opencode-linux-x64.zip | cut -d' ' -f1`
|
||||
.text()
|
||||
.then((x) => x.trim())
|
||||
const macX64Sha = await $`sha256sum ./dist/opencode-darwin-x64.zip | cut -d' ' -f1`
|
||||
.text()
|
||||
.then((x) => x.trim())
|
||||
const macArm64Sha = await $`sha256sum ./dist/opencode-darwin-arm64.zip | cut -d' ' -f1`
|
||||
.text()
|
||||
.then((x) => x.trim())
|
||||
|
||||
const [pkgver, _subver = ""] = Script.version.split(/(-.*)/, 2)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { EOL } from "os"
|
||||
import { Config } from "../../../config/config"
|
||||
import { bootstrap } from "../../bootstrap"
|
||||
import { cmd } from "../cmd"
|
||||
|
|
@ -8,7 +9,7 @@ export const ConfigCommand = cmd({
|
|||
async handler() {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
const config = await Config.get()
|
||||
console.log(JSON.stringify(config, null, 2))
|
||||
process.stdout.write(JSON.stringify(config, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ const FileSearchCommand = cmd({
|
|||
async handler(args) {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
const results = await File.search({ query: args.query })
|
||||
console.log(results.join(EOL))
|
||||
process.stdout.write(results.join(EOL) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -30,7 +30,7 @@ const FileReadCommand = cmd({
|
|||
async handler(args) {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
const content = await File.read(args.path)
|
||||
console.log(content)
|
||||
process.stdout.write(JSON.stringify(content, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -41,7 +41,7 @@ const FileStatusCommand = cmd({
|
|||
async handler() {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
const status = await File.status()
|
||||
console.log(JSON.stringify(status, null, 2))
|
||||
process.stdout.write(JSON.stringify(status, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -57,7 +57,7 @@ const FileListCommand = cmd({
|
|||
async handler(args) {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
const files = await File.list(args.path)
|
||||
console.log(JSON.stringify(files, null, 2))
|
||||
process.stdout.write(JSON.stringify(files, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { LSP } from "../../../lsp"
|
|||
import { bootstrap } from "../../bootstrap"
|
||||
import { cmd } from "../cmd"
|
||||
import { Log } from "../../../util/log"
|
||||
import { EOL } from "os"
|
||||
|
||||
export const LSPCommand = cmd({
|
||||
command: "lsp",
|
||||
|
|
@ -16,7 +17,7 @@ const DiagnosticsCommand = cmd({
|
|||
async handler(args) {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
await LSP.touchFile(args.file, true)
|
||||
console.log(JSON.stringify(await LSP.diagnostics(), null, 2))
|
||||
process.stdout.write(JSON.stringify(await LSP.diagnostics(), null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -28,7 +29,7 @@ export const SymbolsCommand = cmd({
|
|||
await bootstrap(process.cwd(), async () => {
|
||||
using _ = Log.Default.time("symbols")
|
||||
const results = await LSP.workspaceSymbol(args.query)
|
||||
console.log(JSON.stringify(results, null, 2))
|
||||
process.stdout.write(JSON.stringify(results, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -40,7 +41,7 @@ export const DocumentSymbolsCommand = cmd({
|
|||
await bootstrap(process.cwd(), async () => {
|
||||
using _ = Log.Default.time("document-symbols")
|
||||
const results = await LSP.documentSymbol(args.uri)
|
||||
console.log(JSON.stringify(results, null, 2))
|
||||
process.stdout.write(JSON.stringify(results, null, 2) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const TreeCommand = cmd({
|
|||
}),
|
||||
async handler(args) {
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
console.log(await Ripgrep.tree({ cwd: Instance.directory, limit: args.limit }))
|
||||
process.stdout.write(await Ripgrep.tree({ cwd: Instance.directory, limit: args.limit }) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -49,7 +49,7 @@ const FilesCommand = cmd({
|
|||
files.push(file)
|
||||
if (args.limit && files.length >= args.limit) break
|
||||
}
|
||||
console.log(files.join(EOL))
|
||||
process.stdout.write(files.join(EOL) + EOL)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -78,6 +78,6 @@ const SearchCommand = cmd({
|
|||
glob: args.glob as string[] | undefined,
|
||||
limit: args.limit,
|
||||
})
|
||||
console.log(JSON.stringify(results, null, 2))
|
||||
process.stdout.write(JSON.stringify(results, null, 2) + EOL)
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { EOL } from "os"
|
||||
import { Project } from "../../../project/project"
|
||||
import { Log } from "../../../util/log"
|
||||
import { cmd } from "../cmd"
|
||||
|
|
@ -8,7 +9,7 @@ export const ScrapCommand = cmd({
|
|||
async handler() {
|
||||
const timer = Log.Default.time("scrap")
|
||||
const list = await Project.list()
|
||||
console.log(list)
|
||||
process.stdout.write(JSON.stringify(list, null, 2) + EOL)
|
||||
timer.stop()
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import { Hono, type Context } from "hono"
|
||||
import { describeRoute, resolver, validator } from "hono-openapi"
|
||||
import { z } from "zod"
|
||||
import { AsyncQueue } from "../util/queue"
|
||||
|
||||
interface Request {
|
||||
path: string
|
||||
body: any
|
||||
}
|
||||
const TuiRequest = z.object({
|
||||
path: z.string(),
|
||||
body: z.any(),
|
||||
})
|
||||
|
||||
const request = new AsyncQueue<Request>()
|
||||
type TuiRequest = z.infer<typeof TuiRequest>
|
||||
|
||||
const request = new AsyncQueue<TuiRequest>()
|
||||
const response = new AsyncQueue<any>()
|
||||
|
||||
export async function callTui(ctx: Context) {
|
||||
|
|
@ -19,12 +23,47 @@ export async function callTui(ctx: Context) {
|
|||
}
|
||||
|
||||
export const TuiRoute = new Hono()
|
||||
.get("/next", async (c) => {
|
||||
const req = await request.next()
|
||||
return c.json(req)
|
||||
})
|
||||
.post("/response", async (c) => {
|
||||
const body = await c.req.json()
|
||||
response.push(body)
|
||||
return c.json(true)
|
||||
})
|
||||
.get(
|
||||
"/next",
|
||||
describeRoute({
|
||||
description: "Get the next TUI request from the queue",
|
||||
operationId: "tui.control.next",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Next TUI request",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: resolver(TuiRequest),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
const req = await request.next()
|
||||
return c.json(req)
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/response",
|
||||
describeRoute({
|
||||
description: "Submit a response to the TUI request queue",
|
||||
operationId: "tui.control.response",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Response submitted successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: resolver(z.boolean()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
validator("json", z.any()),
|
||||
async (c) => {
|
||||
const body = c.req.valid("json")
|
||||
response.push(body)
|
||||
return c.json(true)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ const parser = lazy(async () => {
|
|||
p.setLanguage(Bash.language as any)
|
||||
return p
|
||||
} catch (e) {
|
||||
const { Parser, Language } = await import("web-tree-sitter")
|
||||
const { default: treeWasm } = await import("web-tree-sitter/web-tree-sitter.wasm" as string, {
|
||||
const { default: Parser } = await import("web-tree-sitter")
|
||||
const { default: treeWasm } = await import("web-tree-sitter/tree-sitter.wasm" as string, {
|
||||
with: { type: "wasm" },
|
||||
})
|
||||
await Parser.init({
|
||||
|
|
@ -53,6 +53,11 @@ export const BashTool = Tool.define("bash", {
|
|||
),
|
||||
}),
|
||||
async execute(params, ctx) {
|
||||
if (params.timeout !== undefined && params.timeout < 0) {
|
||||
throw new Error(
|
||||
`Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`,
|
||||
)
|
||||
}
|
||||
const timeout = Math.min(params.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT)
|
||||
/*
|
||||
const tree = await parser().then((p) => p.parse(params.command))
|
||||
|
|
@ -99,7 +104,10 @@ export const BashTool = Tool.define("bash", {
|
|||
|
||||
// always allow cd if it passes above check
|
||||
if (command[0] !== "cd") {
|
||||
const action = Wildcard.allStructured({ head: command[0], tail: command.slice(1) }, permissions)
|
||||
const action = Wildcard.allStructured(
|
||||
{ head: command[0], tail: command.slice(1) },
|
||||
permissions,
|
||||
)
|
||||
if (action === "deny") {
|
||||
throw new Error(
|
||||
`The user has specifically restricted access to this command, you are not allowed to execute it. Here is the configuration: ${JSON.stringify(permissions)}`,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsgo --noEmit",
|
||||
|
|
|
|||
|
|
@ -4,10 +4,13 @@ if (process.versions.bun !== "1.3.0") {
|
|||
throw new Error("This script requires bun@1.3.0")
|
||||
}
|
||||
|
||||
const CHANNEL = process.env["OPENCODE_CHANNEL"] ?? (await $`git branch --show-current`.text().then((x) => x.trim()))
|
||||
const CHANNEL =
|
||||
process.env["OPENCODE_CHANNEL"] ??
|
||||
(await $`git branch --show-current`.text().then((x) => x.trim()))
|
||||
const IS_PREVIEW = CHANNEL !== "latest"
|
||||
const VERSION = await (async () => {
|
||||
if (IS_PREVIEW) return `0.0.0-${CHANNEL}-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}`
|
||||
if (IS_PREVIEW)
|
||||
return `0.0.0-${CHANNEL}-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}`
|
||||
const version = await fetch("https://registry.npmjs.org/opencode-ai/latest")
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error(res.statusText)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.15.20",
|
||||
"version": "0.15.23",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsgo --noEmit",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { ClientOptions } from "./types.gen.js"
|
||||
import { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from "./client/index.js"
|
||||
import {
|
||||
type Config,
|
||||
type ClientOptions as DefaultClientOptions,
|
||||
createClient,
|
||||
createConfig,
|
||||
} from "./client/index.js"
|
||||
|
||||
/**
|
||||
* The `createClientConfig()` function will be called on client initialization
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ export const createClient = (config: Config = {}): Client => {
|
|||
}
|
||||
|
||||
const parseAs =
|
||||
(opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json"
|
||||
(opts.parseAs === "auto"
|
||||
? getParseAs(response.headers.get("Content-Type"))
|
||||
: opts.parseAs) ?? "json"
|
||||
|
||||
let data: any
|
||||
switch (parseAs) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Auth } from "../core/auth.gen.js"
|
||||
import type { ServerSentEventsOptions, ServerSentEventsResult } from "../core/serverSentEvents.gen.js"
|
||||
import type {
|
||||
ServerSentEventsOptions,
|
||||
ServerSentEventsResult,
|
||||
} from "../core/serverSentEvents.gen.js"
|
||||
import type { Client as CoreClient, Config as CoreConfig } from "../core/types.gen.js"
|
||||
import type { Middleware } from "./utils.gen.js"
|
||||
|
||||
|
|
@ -62,7 +65,11 @@ export interface RequestOptions<
|
|||
}>,
|
||||
Pick<
|
||||
ServerSentEventsOptions<TData>,
|
||||
"onSseError" | "onSseEvent" | "sseDefaultRetryDelay" | "sseMaxRetryAttempts" | "sseMaxRetryDelay"
|
||||
| "onSseError"
|
||||
| "onSseEvent"
|
||||
| "sseDefaultRetryDelay"
|
||||
| "sseMaxRetryAttempts"
|
||||
| "sseMaxRetryDelay"
|
||||
> {
|
||||
/**
|
||||
* Any body that you want to add to your request.
|
||||
|
|
@ -202,7 +209,10 @@ export type Options<
|
|||
ThrowOnError extends boolean = boolean,
|
||||
TResponse = unknown,
|
||||
TResponseStyle extends ResponseStyle = "fields",
|
||||
> = OmitKeys<RequestOptions<TResponse, TResponseStyle, ThrowOnError>, "body" | "path" | "query" | "url"> &
|
||||
> = OmitKeys<
|
||||
RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
|
||||
"body" | "path" | "query" | "url"
|
||||
> &
|
||||
Omit<TData, "url">
|
||||
|
||||
export type OptionsLegacyParser<
|
||||
|
|
@ -211,7 +221,8 @@ export type OptionsLegacyParser<
|
|||
TResponseStyle extends ResponseStyle = "fields",
|
||||
> = TData extends { body?: any }
|
||||
? TData extends { headers?: any }
|
||||
? OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body" | "headers" | "url"> & TData
|
||||
? OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body" | "headers" | "url"> &
|
||||
TData
|
||||
: OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body" | "url"> &
|
||||
TData &
|
||||
Pick<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "headers">
|
||||
|
|
|
|||
|
|
@ -3,11 +3,19 @@
|
|||
import { getAuthToken } from "../core/auth.gen.js"
|
||||
import type { QuerySerializerOptions } from "../core/bodySerializer.gen.js"
|
||||
import { jsonBodySerializer } from "../core/bodySerializer.gen.js"
|
||||
import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from "../core/pathSerializer.gen.js"
|
||||
import {
|
||||
serializeArrayParam,
|
||||
serializeObjectParam,
|
||||
serializePrimitiveParam,
|
||||
} from "../core/pathSerializer.gen.js"
|
||||
import { getUrl } from "../core/utils.gen.js"
|
||||
import type { Client, ClientOptions, Config, RequestOptions } from "./types.gen.js"
|
||||
|
||||
export const createQuerySerializer = <T = unknown>({ allowReserved, array, object }: QuerySerializerOptions = {}) => {
|
||||
export const createQuerySerializer = <T = unknown>({
|
||||
allowReserved,
|
||||
array,
|
||||
object,
|
||||
}: QuerySerializerOptions = {}) => {
|
||||
const querySerializer = (queryParams: T) => {
|
||||
const search: string[] = []
|
||||
if (queryParams && typeof queryParams === "object") {
|
||||
|
|
@ -77,7 +85,9 @@ export const getParseAs = (contentType: string | null): Exclude<Config["parseAs"
|
|||
return "formData"
|
||||
}
|
||||
|
||||
if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
|
||||
if (
|
||||
["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))
|
||||
) {
|
||||
return "blob"
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +107,11 @@ const checkForExistence = (
|
|||
if (!name) {
|
||||
return false
|
||||
}
|
||||
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
|
||||
if (
|
||||
options.headers.has(name) ||
|
||||
options.query?.[name] ||
|
||||
options.headers.get("Cookie")?.includes(`${name}=`)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -162,7 +176,9 @@ export const mergeConfigs = (a: Config, b: Config): Config => {
|
|||
return config
|
||||
}
|
||||
|
||||
export const mergeHeaders = (...headers: Array<Required<Config>["headers"] | undefined>): Headers => {
|
||||
export const mergeHeaders = (
|
||||
...headers: Array<Required<Config>["headers"] | undefined>
|
||||
): Headers => {
|
||||
const mergedHeaders = new Headers()
|
||||
for (const header of headers) {
|
||||
if (!header || typeof header !== "object") {
|
||||
|
|
@ -181,7 +197,10 @@ export const mergeHeaders = (...headers: Array<Required<Config>["headers"] | und
|
|||
} else if (value !== undefined) {
|
||||
// assume object headers are meant to be JSON stringified, i.e. their
|
||||
// content value in OpenAPI specification is 'application/json'
|
||||
mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : (value as string))
|
||||
mergedHeaders.set(
|
||||
key,
|
||||
typeof value === "object" ? JSON.stringify(value) : (value as string),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,7 +216,11 @@ type ErrInterceptor<Err, Res, Req, Options> = (
|
|||
|
||||
type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>
|
||||
|
||||
type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res>
|
||||
type ResInterceptor<Res, Req, Options> = (
|
||||
response: Res,
|
||||
request: Req,
|
||||
options: Options,
|
||||
) => Res | Promise<Res>
|
||||
|
||||
class Interceptors<Interceptor> {
|
||||
_fns: (Interceptor | null)[]
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value:
|
|||
}
|
||||
|
||||
export const formDataBodySerializer = {
|
||||
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): FormData => {
|
||||
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
|
||||
body: T,
|
||||
): FormData => {
|
||||
const data = new FormData()
|
||||
|
||||
Object.entries(body).forEach(([key, value]) => {
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ export const serializeArrayParam = ({
|
|||
value: unknown[]
|
||||
}) => {
|
||||
if (!explode) {
|
||||
const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v as string))).join(
|
||||
separatorArrayNoExplode(style),
|
||||
)
|
||||
const joinedValues = (
|
||||
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
|
||||
).join(separatorArrayNoExplode(style))
|
||||
switch (style) {
|
||||
case "label":
|
||||
return `.${joinedValues}`
|
||||
|
|
@ -106,7 +106,11 @@ export const serializeArrayParam = ({
|
|||
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues
|
||||
}
|
||||
|
||||
export const serializePrimitiveParam = ({ allowReserved, name, value }: SerializePrimitiveParam) => {
|
||||
export const serializePrimitiveParam = ({
|
||||
allowReserved,
|
||||
name,
|
||||
value,
|
||||
}: SerializePrimitiveParam) => {
|
||||
if (value === undefined || value === null) {
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,11 @@ export interface StreamEvent<TData = unknown> {
|
|||
}
|
||||
|
||||
export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
|
||||
stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>
|
||||
stream: AsyncGenerator<
|
||||
TData extends Record<string, unknown> ? TData[keyof TData] : TData,
|
||||
TReturn,
|
||||
TNext
|
||||
>
|
||||
}
|
||||
|
||||
export const createSseClient = <TData = unknown>({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import type { Auth, AuthToken } from "./auth.gen.js"
|
||||
import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer.gen.js"
|
||||
import type {
|
||||
BodySerializer,
|
||||
QuerySerializer,
|
||||
QuerySerializerOptions,
|
||||
} from "./bodySerializer.gen.js"
|
||||
|
||||
export interface Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never> {
|
||||
/**
|
||||
|
|
@ -41,7 +45,10 @@ export interface Config {
|
|||
*/
|
||||
headers?:
|
||||
| RequestInit["headers"]
|
||||
| Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown>
|
||||
| Record<
|
||||
string,
|
||||
string | number | boolean | (string | number | boolean)[] | null | undefined | unknown
|
||||
>
|
||||
/**
|
||||
* The request method.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -73,7 +73,9 @@ export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
|
|||
continue
|
||||
}
|
||||
|
||||
const replaceValue = encodeURIComponent(style === "label" ? `.${value as string}` : (value as string))
|
||||
const replaceValue = encodeURIComponent(
|
||||
style === "label" ? `.${value as string}` : (value as string),
|
||||
)
|
||||
url = url.replace(match, replaceValue)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,10 +138,10 @@ import type {
|
|||
} from "./types.gen.js"
|
||||
import { client as _heyApiClient } from "./client.gen.js"
|
||||
|
||||
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<
|
||||
TData,
|
||||
ThrowOnError
|
||||
> & {
|
||||
export type Options<
|
||||
TData extends TDataShape = TDataShape,
|
||||
ThrowOnError extends boolean = boolean,
|
||||
> = ClientOptions<TData, ThrowOnError> & {
|
||||
/**
|
||||
* You can provide a client instance returned by `createClient()` instead of
|
||||
* individual options. This might be also useful if you want to implement a
|
||||
|
|
@ -169,7 +169,9 @@ class Project extends _HeyApiClient {
|
|||
/**
|
||||
* List all projects
|
||||
*/
|
||||
public list<ThrowOnError extends boolean = false>(options?: Options<ProjectListData, ThrowOnError>) {
|
||||
public list<ThrowOnError extends boolean = false>(
|
||||
options?: Options<ProjectListData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<ProjectListResponses, unknown, ThrowOnError>({
|
||||
url: "/project",
|
||||
...options,
|
||||
|
|
@ -179,7 +181,9 @@ class Project extends _HeyApiClient {
|
|||
/**
|
||||
* Get the current project
|
||||
*/
|
||||
public current<ThrowOnError extends boolean = false>(options?: Options<ProjectCurrentData, ThrowOnError>) {
|
||||
public current<ThrowOnError extends boolean = false>(
|
||||
options?: Options<ProjectCurrentData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<ProjectCurrentResponses, unknown, ThrowOnError>({
|
||||
url: "/project/current",
|
||||
...options,
|
||||
|
|
@ -201,8 +205,14 @@ class Config extends _HeyApiClient {
|
|||
/**
|
||||
* Update config
|
||||
*/
|
||||
public update<ThrowOnError extends boolean = false>(options?: Options<ConfigUpdateData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).patch<ConfigUpdateResponses, ConfigUpdateErrors, ThrowOnError>({
|
||||
public update<ThrowOnError extends boolean = false>(
|
||||
options?: Options<ConfigUpdateData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).patch<
|
||||
ConfigUpdateResponses,
|
||||
ConfigUpdateErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/config",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -215,7 +225,9 @@ class Config extends _HeyApiClient {
|
|||
/**
|
||||
* List all providers
|
||||
*/
|
||||
public providers<ThrowOnError extends boolean = false>(options?: Options<ConfigProvidersData, ThrowOnError>) {
|
||||
public providers<ThrowOnError extends boolean = false>(
|
||||
options?: Options<ConfigProvidersData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<ConfigProvidersResponses, unknown, ThrowOnError>({
|
||||
url: "/config/providers",
|
||||
...options,
|
||||
|
|
@ -261,7 +273,9 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* List all sessions
|
||||
*/
|
||||
public list<ThrowOnError extends boolean = false>(options?: Options<SessionListData, ThrowOnError>) {
|
||||
public list<ThrowOnError extends boolean = false>(
|
||||
options?: Options<SessionListData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<SessionListResponses, unknown, ThrowOnError>({
|
||||
url: "/session",
|
||||
...options,
|
||||
|
|
@ -271,8 +285,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Create a new session
|
||||
*/
|
||||
public create<ThrowOnError extends boolean = false>(options?: Options<SessionCreateData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).post<SessionCreateResponses, SessionCreateErrors, ThrowOnError>({
|
||||
public create<ThrowOnError extends boolean = false>(
|
||||
options?: Options<SessionCreateData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<
|
||||
SessionCreateResponses,
|
||||
SessionCreateErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -285,8 +305,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Delete a session and all its data
|
||||
*/
|
||||
public delete<ThrowOnError extends boolean = false>(options: Options<SessionDeleteData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).delete<SessionDeleteResponses, SessionDeleteErrors, ThrowOnError>({
|
||||
public delete<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionDeleteData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).delete<
|
||||
SessionDeleteResponses,
|
||||
SessionDeleteErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -296,7 +322,11 @@ class Session extends _HeyApiClient {
|
|||
* Get session
|
||||
*/
|
||||
public get<ThrowOnError extends boolean = false>(options: Options<SessionGetData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionGetResponses, SessionGetErrors, ThrowOnError>({
|
||||
return (options.client ?? this._client).get<
|
||||
SessionGetResponses,
|
||||
SessionGetErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -305,8 +335,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Update session properties
|
||||
*/
|
||||
public update<ThrowOnError extends boolean = false>(options: Options<SessionUpdateData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).patch<SessionUpdateResponses, SessionUpdateErrors, ThrowOnError>({
|
||||
public update<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionUpdateData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).patch<
|
||||
SessionUpdateResponses,
|
||||
SessionUpdateErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -319,8 +355,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Get a session's children
|
||||
*/
|
||||
public children<ThrowOnError extends boolean = false>(options: Options<SessionChildrenData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionChildrenResponses, SessionChildrenErrors, ThrowOnError>({
|
||||
public children<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionChildrenData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<
|
||||
SessionChildrenResponses,
|
||||
SessionChildrenErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/children",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -329,8 +371,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Get the todo list for a session
|
||||
*/
|
||||
public todo<ThrowOnError extends boolean = false>(options: Options<SessionTodoData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionTodoResponses, SessionTodoErrors, ThrowOnError>({
|
||||
public todo<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionTodoData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<
|
||||
SessionTodoResponses,
|
||||
SessionTodoErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/todo",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -339,8 +387,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Analyze the app and create an AGENTS.md file
|
||||
*/
|
||||
public init<ThrowOnError extends boolean = false>(options: Options<SessionInitData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionInitResponses, SessionInitErrors, ThrowOnError>({
|
||||
public init<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionInitData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionInitResponses,
|
||||
SessionInitErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/init",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -353,7 +407,9 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Fork an existing session at a specific message
|
||||
*/
|
||||
public fork<ThrowOnError extends boolean = false>(options: Options<SessionForkData, ThrowOnError>) {
|
||||
public fork<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionForkData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<SessionForkResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/fork",
|
||||
...options,
|
||||
|
|
@ -367,8 +423,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Abort a session
|
||||
*/
|
||||
public abort<ThrowOnError extends boolean = false>(options: Options<SessionAbortData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionAbortResponses, SessionAbortErrors, ThrowOnError>({
|
||||
public abort<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionAbortData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionAbortResponses,
|
||||
SessionAbortErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/abort",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -377,8 +439,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Unshare the session
|
||||
*/
|
||||
public unshare<ThrowOnError extends boolean = false>(options: Options<SessionUnshareData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).delete<SessionUnshareResponses, SessionUnshareErrors, ThrowOnError>({
|
||||
public unshare<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionUnshareData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).delete<
|
||||
SessionUnshareResponses,
|
||||
SessionUnshareErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/share",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -387,8 +455,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Share a session
|
||||
*/
|
||||
public share<ThrowOnError extends boolean = false>(options: Options<SessionShareData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionShareResponses, SessionShareErrors, ThrowOnError>({
|
||||
public share<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionShareData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionShareResponses,
|
||||
SessionShareErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/share",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -397,7 +471,9 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Get the diff that resulted from this user message
|
||||
*/
|
||||
public diff<ThrowOnError extends boolean = false>(options: Options<SessionDiffData, ThrowOnError>) {
|
||||
public diff<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionDiffData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<SessionDiffResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/diff",
|
||||
...options,
|
||||
|
|
@ -407,8 +483,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Summarize the session
|
||||
*/
|
||||
public summarize<ThrowOnError extends boolean = false>(options: Options<SessionSummarizeData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionSummarizeResponses, SessionSummarizeErrors, ThrowOnError>({
|
||||
public summarize<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionSummarizeData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionSummarizeResponses,
|
||||
SessionSummarizeErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/summarize",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -421,8 +503,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* List messages for a session
|
||||
*/
|
||||
public messages<ThrowOnError extends boolean = false>(options: Options<SessionMessagesData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionMessagesResponses, SessionMessagesErrors, ThrowOnError>({
|
||||
public messages<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionMessagesData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<
|
||||
SessionMessagesResponses,
|
||||
SessionMessagesErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/message",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -431,8 +519,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Create and send a new message to a session
|
||||
*/
|
||||
public prompt<ThrowOnError extends boolean = false>(options: Options<SessionPromptData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionPromptResponses, SessionPromptErrors, ThrowOnError>({
|
||||
public prompt<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionPromptData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionPromptResponses,
|
||||
SessionPromptErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/message",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -445,8 +539,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Get a message from a session
|
||||
*/
|
||||
public message<ThrowOnError extends boolean = false>(options: Options<SessionMessageData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionMessageResponses, SessionMessageErrors, ThrowOnError>({
|
||||
public message<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionMessageData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<
|
||||
SessionMessageResponses,
|
||||
SessionMessageErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/message/{messageID}",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -455,8 +555,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Send a new command to a session
|
||||
*/
|
||||
public command<ThrowOnError extends boolean = false>(options: Options<SessionCommandData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionCommandResponses, SessionCommandErrors, ThrowOnError>({
|
||||
public command<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionCommandData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionCommandResponses,
|
||||
SessionCommandErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/command",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -469,8 +575,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Run a shell command
|
||||
*/
|
||||
public shell<ThrowOnError extends boolean = false>(options: Options<SessionShellData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionShellResponses, SessionShellErrors, ThrowOnError>({
|
||||
public shell<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionShellData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionShellResponses,
|
||||
SessionShellErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/shell",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -483,8 +595,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Revert a message
|
||||
*/
|
||||
public revert<ThrowOnError extends boolean = false>(options: Options<SessionRevertData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionRevertResponses, SessionRevertErrors, ThrowOnError>({
|
||||
public revert<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionRevertData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionRevertResponses,
|
||||
SessionRevertErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/revert",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -497,8 +615,14 @@ class Session extends _HeyApiClient {
|
|||
/**
|
||||
* Restore all reverted messages
|
||||
*/
|
||||
public unrevert<ThrowOnError extends boolean = false>(options: Options<SessionUnrevertData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionUnrevertResponses, SessionUnrevertErrors, ThrowOnError>({
|
||||
public unrevert<ThrowOnError extends boolean = false>(
|
||||
options: Options<SessionUnrevertData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).post<
|
||||
SessionUnrevertResponses,
|
||||
SessionUnrevertErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/session/{id}/unrevert",
|
||||
...options,
|
||||
})
|
||||
|
|
@ -509,7 +633,9 @@ class Command extends _HeyApiClient {
|
|||
/**
|
||||
* List all commands
|
||||
*/
|
||||
public list<ThrowOnError extends boolean = false>(options?: Options<CommandListData, ThrowOnError>) {
|
||||
public list<ThrowOnError extends boolean = false>(
|
||||
options?: Options<CommandListData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<CommandListResponses, unknown, ThrowOnError>({
|
||||
url: "/command",
|
||||
...options,
|
||||
|
|
@ -531,7 +657,9 @@ class Find extends _HeyApiClient {
|
|||
/**
|
||||
* Find files
|
||||
*/
|
||||
public files<ThrowOnError extends boolean = false>(options: Options<FindFilesData, ThrowOnError>) {
|
||||
public files<ThrowOnError extends boolean = false>(
|
||||
options: Options<FindFilesData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<FindFilesResponses, unknown, ThrowOnError>({
|
||||
url: "/find/file",
|
||||
...options,
|
||||
|
|
@ -541,7 +669,9 @@ class Find extends _HeyApiClient {
|
|||
/**
|
||||
* Find workspace symbols
|
||||
*/
|
||||
public symbols<ThrowOnError extends boolean = false>(options: Options<FindSymbolsData, ThrowOnError>) {
|
||||
public symbols<ThrowOnError extends boolean = false>(
|
||||
options: Options<FindSymbolsData, ThrowOnError>,
|
||||
) {
|
||||
return (options.client ?? this._client).get<FindSymbolsResponses, unknown, ThrowOnError>({
|
||||
url: "/find/symbol",
|
||||
...options,
|
||||
|
|
@ -573,7 +703,9 @@ class File extends _HeyApiClient {
|
|||
/**
|
||||
* Get file status
|
||||
*/
|
||||
public status<ThrowOnError extends boolean = false>(options?: Options<FileStatusData, ThrowOnError>) {
|
||||
public status<ThrowOnError extends boolean = false>(
|
||||
options?: Options<FileStatusData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<FileStatusResponses, unknown, ThrowOnError>({
|
||||
url: "/file/status",
|
||||
...options,
|
||||
|
|
@ -599,7 +731,9 @@ class App extends _HeyApiClient {
|
|||
/**
|
||||
* List all agents
|
||||
*/
|
||||
public agents<ThrowOnError extends boolean = false>(options?: Options<AppAgentsData, ThrowOnError>) {
|
||||
public agents<ThrowOnError extends boolean = false>(
|
||||
options?: Options<AppAgentsData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<AppAgentsResponses, unknown, ThrowOnError>({
|
||||
url: "/agent",
|
||||
...options,
|
||||
|
|
@ -611,7 +745,9 @@ class Mcp extends _HeyApiClient {
|
|||
/**
|
||||
* Get MCP server status
|
||||
*/
|
||||
public status<ThrowOnError extends boolean = false>(options?: Options<McpStatusData, ThrowOnError>) {
|
||||
public status<ThrowOnError extends boolean = false>(
|
||||
options?: Options<McpStatusData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get<McpStatusResponses, unknown, ThrowOnError>({
|
||||
url: "/mcp",
|
||||
...options,
|
||||
|
|
@ -635,8 +771,14 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Append prompt to the TUI
|
||||
*/
|
||||
public appendPrompt<ThrowOnError extends boolean = false>(options?: Options<TuiAppendPromptData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).post<TuiAppendPromptResponses, TuiAppendPromptErrors, ThrowOnError>({
|
||||
public appendPrompt<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiAppendPromptData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<
|
||||
TuiAppendPromptResponses,
|
||||
TuiAppendPromptErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/tui/append-prompt",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -649,7 +791,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Open the help dialog
|
||||
*/
|
||||
public openHelp<ThrowOnError extends boolean = false>(options?: Options<TuiOpenHelpData, ThrowOnError>) {
|
||||
public openHelp<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiOpenHelpData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiOpenHelpResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/open-help",
|
||||
...options,
|
||||
|
|
@ -659,7 +803,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Open the session dialog
|
||||
*/
|
||||
public openSessions<ThrowOnError extends boolean = false>(options?: Options<TuiOpenSessionsData, ThrowOnError>) {
|
||||
public openSessions<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiOpenSessionsData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiOpenSessionsResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/open-sessions",
|
||||
...options,
|
||||
|
|
@ -669,7 +815,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Open the theme dialog
|
||||
*/
|
||||
public openThemes<ThrowOnError extends boolean = false>(options?: Options<TuiOpenThemesData, ThrowOnError>) {
|
||||
public openThemes<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiOpenThemesData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiOpenThemesResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/open-themes",
|
||||
...options,
|
||||
|
|
@ -679,7 +827,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Open the model dialog
|
||||
*/
|
||||
public openModels<ThrowOnError extends boolean = false>(options?: Options<TuiOpenModelsData, ThrowOnError>) {
|
||||
public openModels<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiOpenModelsData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiOpenModelsResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/open-models",
|
||||
...options,
|
||||
|
|
@ -689,7 +839,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Submit the prompt
|
||||
*/
|
||||
public submitPrompt<ThrowOnError extends boolean = false>(options?: Options<TuiSubmitPromptData, ThrowOnError>) {
|
||||
public submitPrompt<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiSubmitPromptData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiSubmitPromptResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/submit-prompt",
|
||||
...options,
|
||||
|
|
@ -699,7 +851,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Clear the prompt
|
||||
*/
|
||||
public clearPrompt<ThrowOnError extends boolean = false>(options?: Options<TuiClearPromptData, ThrowOnError>) {
|
||||
public clearPrompt<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiClearPromptData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiClearPromptResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/clear-prompt",
|
||||
...options,
|
||||
|
|
@ -709,8 +863,14 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Execute a TUI command (e.g. agent_cycle)
|
||||
*/
|
||||
public executeCommand<ThrowOnError extends boolean = false>(options?: Options<TuiExecuteCommandData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).post<TuiExecuteCommandResponses, TuiExecuteCommandErrors, ThrowOnError>({
|
||||
public executeCommand<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiExecuteCommandData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<
|
||||
TuiExecuteCommandResponses,
|
||||
TuiExecuteCommandErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/tui/execute-command",
|
||||
...options,
|
||||
headers: {
|
||||
|
|
@ -723,7 +883,9 @@ class Tui extends _HeyApiClient {
|
|||
/**
|
||||
* Show a toast notification in the TUI
|
||||
*/
|
||||
public showToast<ThrowOnError extends boolean = false>(options?: Options<TuiShowToastData, ThrowOnError>) {
|
||||
public showToast<ThrowOnError extends boolean = false>(
|
||||
options?: Options<TuiShowToastData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).post<TuiShowToastResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/show-toast",
|
||||
...options,
|
||||
|
|
@ -769,8 +931,14 @@ class Event extends _HeyApiClient {
|
|||
/**
|
||||
* Get events
|
||||
*/
|
||||
public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
|
||||
public subscribe<ThrowOnError extends boolean = false>(
|
||||
options?: Options<EventSubscribeData, ThrowOnError>,
|
||||
) {
|
||||
return (options?.client ?? this._client).get.sse<
|
||||
EventSubscribeResponses,
|
||||
unknown,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/event",
|
||||
...options,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -517,6 +517,10 @@ export type Config = {
|
|||
}
|
||||
}>
|
||||
}
|
||||
/**
|
||||
* Number of retries for chat completions on failure
|
||||
*/
|
||||
chatMaxRetries?: number
|
||||
disable_paste_summary?: boolean
|
||||
}
|
||||
}
|
||||
|
|
@ -670,7 +674,12 @@ export type AssistantMessage = {
|
|||
created: number
|
||||
completed?: number
|
||||
}
|
||||
error?: ProviderAuthError | UnknownError | MessageOutputLengthError | MessageAbortedError | ApiError
|
||||
error?:
|
||||
| ProviderAuthError
|
||||
| UnknownError
|
||||
| MessageOutputLengthError
|
||||
| MessageAbortedError
|
||||
| ApiError
|
||||
system: Array<string>
|
||||
parentID: string
|
||||
modelID: string
|
||||
|
|
@ -1309,7 +1318,12 @@ export type EventSessionError = {
|
|||
type: "session.error"
|
||||
properties: {
|
||||
sessionID?: string
|
||||
error?: ProviderAuthError | UnknownError | MessageOutputLengthError | MessageAbortedError | ApiError
|
||||
error?:
|
||||
| ProviderAuthError
|
||||
| UnknownError
|
||||
| MessageOutputLengthError
|
||||
| MessageAbortedError
|
||||
| ApiError
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
22
packages/sdk/python/.gitignore
vendored
Normal file
22
packages/sdk/python/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
__pycache__/
|
||||
*.py[cod]
|
||||
*.egg-info/
|
||||
.build/
|
||||
build/
|
||||
dist/
|
||||
.coverage
|
||||
htmlcov/
|
||||
.mypy_cache/
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.venv/
|
||||
.conda/
|
||||
.env
|
||||
.DS_Store
|
||||
openapi.json
|
||||
site/
|
||||
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
82
packages/sdk/python/README.md
Normal file
82
packages/sdk/python/README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Opencode Python SDK
|
||||
|
||||
This package provides a Python SDK for the Opencode API. It is generated using openapi-python-client (not Stainless).
|
||||
|
||||
|
||||
Documentation
|
||||
- Full docs: see `mkdocs` site under `packages/sdk/python/docs/`
|
||||
- Preview locally:
|
||||
```bash
|
||||
uv run --project packages/sdk/python mkdocs serve -f packages/sdk/python/mkdocs.yml
|
||||
```
|
||||
|
||||
Badges
|
||||
- PyPI: https://img.shields.io/pypi/v/opencode-ai?style=flat-square
|
||||
|
||||
Requirements
|
||||
- Python 3.8+
|
||||
- uv (recommended) -> https://docs.astral.sh/uv/
|
||||
- openapi-python-client (invoked via `uvx`)
|
||||
|
||||
Install uv
|
||||
```bash
|
||||
# macOS/Linux
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
```
|
||||
|
||||
Set up the environment (from this directory)
|
||||
```bash
|
||||
uv sync --dev
|
||||
```
|
||||
|
||||
Generate client code (from CLI-generated spec)
|
||||
```bash
|
||||
# From repository root OR from this directory
|
||||
uv run python packages/sdk/python/scripts/generate.py --source cli
|
||||
```
|
||||
|
||||
Alternatively, fetch spec from a running server
|
||||
```bash
|
||||
uv run python packages/sdk/python/scripts/generate.py --source server --server-url http://localhost:4096/doc
|
||||
```
|
||||
|
||||
This will:
|
||||
1) Produce an OpenAPI spec from the local CLI or a running server
|
||||
2) Run openapi-python-client (via `uvx`) to generate client code
|
||||
3) Copy the generated Python package into src/opencode_ai
|
||||
|
||||
Usage (after generation)
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient(base_url="http://localhost:4096")
|
||||
print(client.get_config())
|
||||
|
||||
# See examples/basic_usage.py for more details
|
||||
|
||||
# Streaming events (sync)
|
||||
for event in client.subscribe_events():
|
||||
print(event)
|
||||
break
|
||||
|
||||
# Error handling and retries
|
||||
# Set retries>0 to enable exponential backoff for transient errors like 429/5xx
|
||||
client = OpenCodeClient(retries=2, backoff_factor=0.1)
|
||||
|
||||
# Async usage example
|
||||
# uv run --project packages/sdk/python python - <<'PY'
|
||||
# import asyncio
|
||||
# from opencode_ai import OpenCodeClient
|
||||
# async def main():
|
||||
# client = OpenCodeClient()
|
||||
# async for event in client.subscribe_events_async():
|
||||
# print(event)
|
||||
# break
|
||||
# asyncio.run(main())
|
||||
# PY
|
||||
```
|
||||
|
||||
Notes
|
||||
- We intentionally do not use Stainless for the Python SDK.
|
||||
- The generator targets OpenAPI 3.1 emitted by the opencode server at /doc.
|
||||
- See scripts/generate.py for details and customization points.
|
||||
19
packages/sdk/python/docs/generation.md
Normal file
19
packages/sdk/python/docs/generation.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generation workflow
|
||||
|
||||
The SDK is generated from the Opencode server's OpenAPI 3.1 spec.
|
||||
|
||||
Two source modes are supported:
|
||||
- CLI (default): runs `bun dev generate` to emit the OpenAPI JSON
|
||||
- Server: fetches `http://localhost:4096/doc` from a running server
|
||||
|
||||
Generator command
|
||||
```bash
|
||||
# From repo root
|
||||
uv run --project packages/sdk/python python packages/sdk/python/scripts/generate.py --source cli
|
||||
# Or
|
||||
uv run --project packages/sdk/python python packages/sdk/python/scripts/generate.py --source server --server-url http://localhost:4096/doc
|
||||
```
|
||||
|
||||
Post-generation
|
||||
- The generator injects `extras.py` (OpenCodeClient) and patches `__init__.py` to export it
|
||||
- Code is formatted with `ruff` (imports) and `black`
|
||||
11
packages/sdk/python/docs/index.md
Normal file
11
packages/sdk/python/docs/index.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Opencode Python SDK
|
||||
|
||||
The official Python client for the Opencode API, generated from the OpenAPI spec and extended with ergonomic helpers.
|
||||
|
||||
Highlights
|
||||
- Provider-agnostic client generated from OpenAPI 3.1
|
||||
- Thin convenience wrapper (OpenCodeClient) for common tasks
|
||||
- Sync and async SSE streaming for live event feeds
|
||||
- First-class uv support for development
|
||||
|
||||
If you're new, start with Quickstart or Installation in the navigation.
|
||||
27
packages/sdk/python/docs/installation.md
Normal file
27
packages/sdk/python/docs/installation.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Installation
|
||||
|
||||
Requirements
|
||||
- Python 3.8+
|
||||
- uv (recommended) -> https://docs.astral.sh/uv/
|
||||
|
||||
Install uv
|
||||
```bash
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
```
|
||||
|
||||
Project setup
|
||||
```bash
|
||||
# From repo root or this directory
|
||||
uv sync --dev --project packages/sdk/python
|
||||
```
|
||||
|
||||
Using pip (alternative)
|
||||
```bash
|
||||
pip install opencode-ai
|
||||
```
|
||||
|
||||
Preview docs locally
|
||||
```bash
|
||||
# From repo root
|
||||
uv run --project packages/sdk/python mkdocs serve -f packages/sdk/python/mkdocs.yml
|
||||
```
|
||||
24
packages/sdk/python/docs/publishing.md
Normal file
24
packages/sdk/python/docs/publishing.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Publishing (maintainers)
|
||||
|
||||
Automated publishing runs on GitHub Releases.
|
||||
|
||||
Workflow
|
||||
- Create a new Release (the tag value becomes the package version)
|
||||
- The `publish-python-sdk` workflow will:
|
||||
- Generate the SDK from OpenAPI (CLI path)
|
||||
- Set the version in `pyproject.toml` and generator config
|
||||
- Build wheel/sdist and upload to PyPI
|
||||
|
||||
Prerequisites
|
||||
- Repository secret: `PYPI_API_TOKEN`
|
||||
|
||||
Manual publish
|
||||
```bash
|
||||
# TestPyPI
|
||||
REPOSITORY=testpypi PYPI_TOKEN=$TEST_PYPI_API_TOKEN \
|
||||
uv run --project packages/sdk/python python packages/sdk/python/scripts/publish.py
|
||||
|
||||
# PyPI
|
||||
REPOSITORY=pypi PYPI_TOKEN=$PYPI_API_TOKEN \
|
||||
uv run --project packages/sdk/python python packages/sdk/python/scripts/publish.py
|
||||
```
|
||||
22
packages/sdk/python/docs/quickstart.md
Normal file
22
packages/sdk/python/docs/quickstart.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Quickstart
|
||||
|
||||
Create a client and make your first calls.
|
||||
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient(base_url="http://localhost:4096")
|
||||
|
||||
# List projects
|
||||
for p in client.list_projects() or []:
|
||||
print(p.id, p.directory)
|
||||
|
||||
# Get path info
|
||||
path = client.get_path()
|
||||
print(path.directory)
|
||||
|
||||
# Stream events (sync)
|
||||
for event in client.subscribe_events():
|
||||
print(event)
|
||||
break
|
||||
```
|
||||
15
packages/sdk/python/docs/testing.md
Normal file
15
packages/sdk/python/docs/testing.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Testing
|
||||
|
||||
Run unit, mock, and integration tests.
|
||||
|
||||
```bash
|
||||
# Sync dev dependencies
|
||||
uv sync --dev --project packages/sdk/python
|
||||
|
||||
# Run tests
|
||||
uv run --project packages/sdk/python pytest -q
|
||||
```
|
||||
|
||||
Notes
|
||||
- Integration test starts a headless opencode server via Bun in a subprocess
|
||||
- SSE behavior is validated using real streaming from the server
|
||||
21
packages/sdk/python/docs/usage/configuration.md
Normal file
21
packages/sdk/python/docs/usage/configuration.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Configuration
|
||||
|
||||
OpenCodeClient accepts common options for auth, timeouts, and retries.
|
||||
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient(
|
||||
base_url="http://localhost:4096",
|
||||
token="pypi-or-other-token",
|
||||
auth_header_name="Authorization",
|
||||
auth_prefix="Bearer",
|
||||
timeout=30.0, # seconds
|
||||
retries=2,
|
||||
backoff_factor=0.2, # exponential backoff
|
||||
)
|
||||
```
|
||||
|
||||
- Auth: sets the header `{auth_header_name}: {auth_prefix} {token}` when `token` is provided
|
||||
- Retries: retry on transient httpx.RequestError and 429/5xx
|
||||
- Timeouts: passed to httpx.Timeout
|
||||
22
packages/sdk/python/docs/usage/files_projects.md
Normal file
22
packages/sdk/python/docs/usage/files_projects.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Files & Projects
|
||||
|
||||
Access file status and project information.
|
||||
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient()
|
||||
|
||||
# Projects
|
||||
for p in client.list_projects() or []:
|
||||
print(p.id, p.directory)
|
||||
|
||||
# Current path
|
||||
pinfo = client.get_path()
|
||||
print(pinfo.directory)
|
||||
|
||||
# File status
|
||||
files = client.file_status() or []
|
||||
for f in files:
|
||||
print(f.path, f.type)
|
||||
```
|
||||
18
packages/sdk/python/docs/usage/sessions.md
Normal file
18
packages/sdk/python/docs/usage/sessions.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Sessions
|
||||
|
||||
List sessions and inspect them. The wrapper exposes a convenience method while the generated API remains available under `opencode_ai.api.default`.
|
||||
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
from opencode_ai.api.default import session_list as generated
|
||||
|
||||
client = OpenCodeClient()
|
||||
|
||||
# Wrapper
|
||||
sessions = client.list_sessions() or []
|
||||
|
||||
# Generated function
|
||||
sessions2 = generated.sync(client=client.client)
|
||||
|
||||
print(len(sessions), len(sessions2))
|
||||
```
|
||||
29
packages/sdk/python/docs/usage/streaming.md
Normal file
29
packages/sdk/python/docs/usage/streaming.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Streaming (SSE)
|
||||
|
||||
Subscribe to the event stream. The wrapper provides both sync and async interfaces.
|
||||
|
||||
```python
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient()
|
||||
|
||||
# Sync streaming
|
||||
for event in client.subscribe_events():
|
||||
print(event)
|
||||
break
|
||||
```
|
||||
|
||||
Async variant:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from opencode_ai import OpenCodeClient
|
||||
|
||||
async def main():
|
||||
client = OpenCodeClient()
|
||||
async for event in client.subscribe_events_async():
|
||||
print(event)
|
||||
break
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
19
packages/sdk/python/examples/basic_usage.py
Normal file
19
packages/sdk/python/examples/basic_usage.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Basic usage example (placeholder)
|
||||
# After generating the client, this should reflect actual client entrypoints.
|
||||
|
||||
try:
|
||||
from opencode_ai import client # type: ignore
|
||||
except Exception: # pragma: no cover
|
||||
client = None
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if client is None:
|
||||
print("Client not generated yet. Run the generator first:")
|
||||
print(" uv run python packages/sdk/python/scripts/generate.py")
|
||||
return
|
||||
print("Replace this with real example code once the client is generated.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
6
packages/sdk/python/examples/file_status.py
Normal file
6
packages/sdk/python/examples/file_status.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient()
|
||||
files = client.file_status() or []
|
||||
for f in files:
|
||||
print(f.path, f.type)
|
||||
4
packages/sdk/python/examples/session_list.py
Normal file
4
packages/sdk/python/examples/session_list.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
from opencode_ai import OpenCodeClient
|
||||
|
||||
client = OpenCodeClient()
|
||||
print([s.id for s in client.list_sessions() or []])
|
||||
29
packages/sdk/python/mkdocs.yml
Normal file
29
packages/sdk/python/mkdocs.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
site_name: Opencode Python SDK
|
||||
site_description: Official Python SDK for the Opencode API
|
||||
site_url: https://opencode.ai
|
||||
repo_url: https://github.com/sst/opencode
|
||||
repo_name: sst/opencode
|
||||
edit_uri: ''
|
||||
theme:
|
||||
name: material
|
||||
features:
|
||||
- navigation.tabs
|
||||
- navigation.sections
|
||||
- content.code.copy
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- codehilite
|
||||
- toc:
|
||||
permalink: true
|
||||
nav:
|
||||
- Overview: index.md
|
||||
- Installation: installation.md
|
||||
- Quickstart: quickstart.md
|
||||
- Usage:
|
||||
- Configuration: usage/configuration.md
|
||||
- Sessions: usage/sessions.md
|
||||
- Files & Projects: usage/files_projects.md
|
||||
- Streaming (SSE): usage/streaming.md
|
||||
- Generation: generation.md
|
||||
- Testing: testing.md
|
||||
- Publishing (maintainers): publishing.md
|
||||
5
packages/sdk/python/openapi-python-client.yaml
Normal file
5
packages/sdk/python/openapi-python-client.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Configuration for openapi-python-client
|
||||
# Ensures consistent project and package names and version when generating.
|
||||
project_name_override: opencode-ai
|
||||
package_name_override: opencode_ai
|
||||
package_version_override: 0.1.0
|
||||
56
packages/sdk/python/pyproject.toml
Normal file
56
packages/sdk/python/pyproject.toml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
[build-system]
|
||||
requires = ["hatchling>=1.17.0"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "opencode-ai"
|
||||
version = "0.1.0"
|
||||
description = "Python client for the Opencode API (generated via openapi-python-client)"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{ name = "Opencode Authors", email = "support@sst.dev" }
|
||||
]
|
||||
dependencies = [
|
||||
"httpx>=0.27.0",
|
||||
"pydantic>=2.0.0",
|
||||
"python-dateutil>=2.8.2"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://opencode.ai"
|
||||
Repository = "https://github.com/sst/opencode"
|
||||
|
||||
[tool.uv]
|
||||
# Development-time dependencies installed with `uv sync --dev`
|
||||
dev-dependencies = [
|
||||
"openapi-python-client",
|
||||
"black",
|
||||
"isort",
|
||||
"ruff",
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"sseclient-py",
|
||||
"build",
|
||||
"twine",
|
||||
"mkdocs",
|
||||
"mkdocs-material",
|
||||
]
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target-version = ["py38", "py39", "py310", "py311", "py312"]
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 120
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
select = ["E", "F", "I", "UP"]
|
||||
ignore = []
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "-q"
|
||||
pythonpath = ["src"]
|
||||
210
packages/sdk/python/scripts/generate.py
Normal file
210
packages/sdk/python/scripts/generate.py
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate the Opencode Python SDK using openapi-python-client and place it under src/opencode_ai.
|
||||
|
||||
Steps:
|
||||
- Generate OpenAPI JSON from the local CLI (bun dev generate)
|
||||
- Run openapi-python-client (via `uvx` if available, else fallback to PATH)
|
||||
- Copy the generated module into src/opencode_ai
|
||||
|
||||
Requires:
|
||||
- Bun installed (for `bun dev generate`)
|
||||
- uv installed (recommended) to run `uvx openapi-python-client`
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
def run(cmd: list[str], cwd: Path | None = None) -> subprocess.CompletedProcess:
|
||||
print("$", " ".join(cmd))
|
||||
return subprocess.run(cmd, cwd=str(cwd) if cwd else None, check=True, capture_output=True, text=True)
|
||||
|
||||
|
||||
def find_repo_root(start: Path) -> Path:
|
||||
p = start
|
||||
for _ in range(10):
|
||||
if (p / ".git").exists() or (p / "sst.config.ts").exists():
|
||||
return p
|
||||
if p.parent == p:
|
||||
break
|
||||
p = p.parent
|
||||
# Fallback: assume 4 levels up from scripts/
|
||||
return start.parents[4]
|
||||
|
||||
|
||||
def write_json(path: Path, content: str) -> None:
|
||||
# Validate JSON before writing
|
||||
json.loads(content)
|
||||
path.write_text(content)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Generate the Opencode Python SDK from OpenAPI spec.")
|
||||
parser.add_argument(
|
||||
"--source", choices=["cli", "server"], default="cli", help="Where to fetch the OpenAPI spec from"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--server-url",
|
||||
default="http://localhost:4096/doc",
|
||||
help="OpenAPI document URL when --source=server",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out-spec",
|
||||
default=None,
|
||||
help="Output path for the OpenAPI spec (defaults to packages/sdk/python/openapi.json)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--only-spec",
|
||||
action="store_true",
|
||||
help="Only fetch and write the OpenAPI spec without generating the client",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
sdk_dir = script_dir.parent
|
||||
repo_root = find_repo_root(script_dir)
|
||||
opencode_dir = repo_root / "packages" / "opencode"
|
||||
|
||||
openapi_json = Path(args.out_spec) if args.out_spec else (sdk_dir / "openapi.json")
|
||||
build_dir = sdk_dir / ".build"
|
||||
out_pkg_dir = sdk_dir / "src" / "opencode_ai"
|
||||
|
||||
build_dir.mkdir(parents=True, exist_ok=True)
|
||||
(sdk_dir / "src").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 1) Obtain OpenAPI spec
|
||||
if args.source == "server":
|
||||
print(f"Fetching OpenAPI spec from {args.server_url} ...")
|
||||
try:
|
||||
with urlopen(args.server_url) as resp:
|
||||
if resp.status != 200:
|
||||
print(f"ERROR: GET {args.server_url} -> HTTP {resp.status}", file=sys.stderr)
|
||||
return 1
|
||||
text = resp.read().decode("utf-8")
|
||||
except Exception as e:
|
||||
print(f"ERROR: Failed to fetch from server: {e}", file=sys.stderr)
|
||||
return 1
|
||||
try:
|
||||
write_json(openapi_json, text)
|
||||
except json.JSONDecodeError as je:
|
||||
print("ERROR: Response from server was not valid JSON:", file=sys.stderr)
|
||||
print(str(je), file=sys.stderr)
|
||||
return 1
|
||||
print(f"Wrote OpenAPI spec to {openapi_json}")
|
||||
else:
|
||||
print("Generating OpenAPI spec via 'bun dev generate' ...")
|
||||
try:
|
||||
proc = run(["bun", "dev", "generate"], cwd=opencode_dir)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e.stdout)
|
||||
print(e.stderr, file=sys.stderr)
|
||||
print(
|
||||
"ERROR: Failed to run 'bun dev generate'. Ensure Bun is installed and available in PATH.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
try:
|
||||
write_json(openapi_json, proc.stdout)
|
||||
except json.JSONDecodeError as je:
|
||||
print("ERROR: Output from 'bun dev generate' was not valid JSON:", file=sys.stderr)
|
||||
print(str(je), file=sys.stderr)
|
||||
return 1
|
||||
print(f"Wrote OpenAPI spec to {openapi_json}")
|
||||
|
||||
if args.only_spec:
|
||||
print("Spec written; skipping client generation (--only-spec).")
|
||||
return 0
|
||||
|
||||
# 2) Run openapi-python-client
|
||||
print("Running openapi-python-client generate ...")
|
||||
# Prefer uvx if available
|
||||
use_uvx = shutil.which("uvx") is not None
|
||||
cmd = (["uvx", "openapi-python-client", "generate"] if use_uvx else ["openapi-python-client", "generate"]) + [
|
||||
"--path",
|
||||
str(openapi_json),
|
||||
"--output-path",
|
||||
str(build_dir),
|
||||
"--overwrite",
|
||||
"--config",
|
||||
str(sdk_dir / "openapi-python-client.yaml"),
|
||||
]
|
||||
|
||||
try:
|
||||
run(cmd, cwd=sdk_dir)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e.stdout)
|
||||
print(e.stderr, file=sys.stderr)
|
||||
print(
|
||||
"ERROR: Failed to run openapi-python-client. Install uv and try again: curl -LsSf https://astral.sh/uv/install.sh | sh",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
# 3) Locate generated module directory and copy to src/opencode_ai
|
||||
generated_module: Path | None = None
|
||||
for candidate in build_dir.rglob("__init__.py"):
|
||||
if candidate.parent.name.startswith("."):
|
||||
continue
|
||||
siblings = {p.name for p in candidate.parent.glob("*.py")}
|
||||
if "client.py" in siblings or "api_client.py" in siblings:
|
||||
generated_module = candidate.parent
|
||||
break
|
||||
|
||||
if not generated_module:
|
||||
print("ERROR: Could not locate generated module directory in .build", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print(f"Found generated module at {generated_module}")
|
||||
|
||||
# Clean target then copy
|
||||
if out_pkg_dir.exists():
|
||||
shutil.rmtree(out_pkg_dir)
|
||||
shutil.copytree(generated_module, out_pkg_dir)
|
||||
|
||||
# Inject local extras from template if present
|
||||
extras_template = sdk_dir / "templates" / "extras.py"
|
||||
if extras_template.exists():
|
||||
(out_pkg_dir / "extras.py").write_text(extras_template.read_text())
|
||||
|
||||
# Patch __init__ to export OpenCodeClient if present
|
||||
init_path = out_pkg_dir / "__init__.py"
|
||||
if init_path.exists() and (out_pkg_dir / "extras.py").exists():
|
||||
init_text = (
|
||||
'"""A client library for accessing opencode\n\n'
|
||||
"This package is generated by openapi-python-client.\n"
|
||||
"A thin convenience wrapper `OpenCodeClient` is also provided.\n"
|
||||
'"""\n\n'
|
||||
"from .client import AuthenticatedClient, Client\n"
|
||||
"from .extras import OpenCodeClient\n\n"
|
||||
"__all__ = (\n"
|
||||
' "AuthenticatedClient",\n'
|
||||
' "Client",\n'
|
||||
' "OpenCodeClient",\n'
|
||||
")\n"
|
||||
)
|
||||
init_path.write_text(init_text)
|
||||
|
||||
print(f"Copied generated client to {out_pkg_dir}")
|
||||
|
||||
# 4) Format generated code
|
||||
try:
|
||||
run(["uv", "run", "--project", str(sdk_dir), "ruff", "check", "--select", "I", "--fix", str(out_pkg_dir)])
|
||||
run(["uv", "run", "--project", str(sdk_dir), "black", str(out_pkg_dir)])
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("WARNING: formatting failed; continuing", file=sys.stderr)
|
||||
print(e.stdout)
|
||||
print(e.stderr, file=sys.stderr)
|
||||
|
||||
print("Done.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
68
packages/sdk/python/scripts/publish.py
Normal file
68
packages/sdk/python/scripts/publish.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Python SDK publishing helper.
|
||||
|
||||
- Builds sdist and wheel using `python -m build` into dist/
|
||||
- Uploads using twine. Configure either TestPyPI or PyPI via environment:
|
||||
|
||||
Environment variables:
|
||||
REPOSITORY : "pypi" (default) or "testpypi"
|
||||
PYPI_TOKEN : API token (e.g., pypi-XXXX). For TestPyPI, use the TestPyPI token.
|
||||
|
||||
Examples:
|
||||
REPOSITORY=testpypi PYPI_TOKEN=${{TEST_PYPI_API_TOKEN}} uv run --project packages/sdk/python python packages/sdk/python/scripts/publish.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def run(cmd: list[str], cwd: Path | None = None) -> None:
|
||||
print("$", " ".join(cmd))
|
||||
subprocess.run(cmd, cwd=str(cwd) if cwd else None, check=True)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
sdk_dir = Path(__file__).resolve().parent.parent
|
||||
repo = os.environ.get("REPOSITORY", "pypi").strip()
|
||||
token = os.environ.get("PYPI_TOKEN")
|
||||
if not token:
|
||||
print("ERROR: PYPI_TOKEN not set", flush=True)
|
||||
return 1
|
||||
|
||||
dist = sdk_dir / "dist"
|
||||
if dist.exists():
|
||||
for f in dist.iterdir():
|
||||
f.unlink()
|
||||
|
||||
# Build
|
||||
run(["python", "-m", "build"], cwd=sdk_dir)
|
||||
|
||||
# Upload
|
||||
repo_url = {
|
||||
"pypi": "https://upload.pypi.org/legacy/",
|
||||
"testpypi": "https://test.pypi.org/legacy/",
|
||||
}.get(repo, repo)
|
||||
|
||||
env = os.environ.copy()
|
||||
env["TWINE_USERNAME"] = "__token__"
|
||||
env["TWINE_PASSWORD"] = token
|
||||
|
||||
print(f"Uploading to {repo_url}")
|
||||
subprocess.run(
|
||||
["python", "-m", "twine", "check", "dist/*"], cwd=sdk_dir, check=True
|
||||
)
|
||||
subprocess.run(
|
||||
["python", "-m", "twine", "upload", "--repository-url", repo_url, "dist/*"],
|
||||
cwd=sdk_dir,
|
||||
check=True,
|
||||
env=env,
|
||||
)
|
||||
print("Publish complete")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
14
packages/sdk/python/src/opencode_ai/__init__.py
Normal file
14
packages/sdk/python/src/opencode_ai/__init__.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
"""A client library for accessing opencode
|
||||
|
||||
This package is generated by openapi-python-client.
|
||||
A thin convenience wrapper `OpenCodeClient` is also provided.
|
||||
"""
|
||||
|
||||
from .client import AuthenticatedClient, Client
|
||||
from .extras import OpenCodeClient
|
||||
|
||||
__all__ = (
|
||||
"AuthenticatedClient",
|
||||
"Client",
|
||||
"OpenCodeClient",
|
||||
)
|
||||
1
packages/sdk/python/src/opencode_ai/api/__init__.py
Normal file
1
packages/sdk/python/src/opencode_ai/api/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
"""Contains methods for accessing the API"""
|
||||
|
|
@ -0,0 +1 @@
|
|||
"""Contains endpoint functions for accessing the API"""
|
||||
160
packages/sdk/python/src/opencode_ai/api/default/app_agents.py
Normal file
160
packages/sdk/python/src/opencode_ai/api/default/app_agents.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.agent import Agent
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/agent",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[list["Agent"]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = []
|
||||
_response_200 = response.json()
|
||||
for response_200_item_data in _response_200:
|
||||
response_200_item = Agent.from_dict(response_200_item_data)
|
||||
|
||||
response_200.append(response_200_item)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[list["Agent"]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Agent"]]:
|
||||
"""List all agents
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Agent']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Agent"]]:
|
||||
"""List all agents
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Agent']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Agent"]]:
|
||||
"""List all agents
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Agent']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Agent"]]:
|
||||
"""List all agents
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Agent']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
164
packages/sdk/python/src/opencode_ai/api/default/command_list.py
Normal file
164
packages/sdk/python/src/opencode_ai/api/default/command_list.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.command import Command
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/command",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Optional[list["Command"]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = []
|
||||
_response_200 = response.json()
|
||||
for response_200_item_data in _response_200:
|
||||
response_200_item = Command.from_dict(response_200_item_data)
|
||||
|
||||
response_200.append(response_200_item)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Response[list["Command"]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Command"]]:
|
||||
"""List all commands
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Command']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Command"]]:
|
||||
"""List all commands
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Command']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Command"]]:
|
||||
"""List all commands
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Command']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Command"]]:
|
||||
"""List all commands
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Command']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
155
packages/sdk/python/src/opencode_ai/api/default/config_get.py
Normal file
155
packages/sdk/python/src/opencode_ai/api/default/config_get.py
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.config import Config
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/config",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Config]:
|
||||
if response.status_code == 200:
|
||||
response_200 = Config.from_dict(response.json())
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Config]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Config]:
|
||||
"""Get config info
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Config]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Config]:
|
||||
"""Get config info
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Config
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Config]:
|
||||
"""Get config info
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Config]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Config]:
|
||||
"""Get config info
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Config
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.config_providers_response_200 import ConfigProvidersResponse200
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/config/providers",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Optional[ConfigProvidersResponse200]:
|
||||
if response.status_code == 200:
|
||||
response_200 = ConfigProvidersResponse200.from_dict(response.json())
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Response[ConfigProvidersResponse200]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[ConfigProvidersResponse200]:
|
||||
"""List all providers
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[ConfigProvidersResponse200]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[ConfigProvidersResponse200]:
|
||||
"""List all providers
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
ConfigProvidersResponse200
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[ConfigProvidersResponse200]:
|
||||
"""List all providers
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[ConfigProvidersResponse200]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[ConfigProvidersResponse200]:
|
||||
"""List all providers
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
ConfigProvidersResponse200
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,447 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.event_file_edited import EventFileEdited
|
||||
from ...models.event_file_watcher_updated import EventFileWatcherUpdated
|
||||
from ...models.event_ide_installed import EventIdeInstalled
|
||||
from ...models.event_installation_updated import EventInstallationUpdated
|
||||
from ...models.event_lsp_client_diagnostics import EventLspClientDiagnostics
|
||||
from ...models.event_message_part_removed import EventMessagePartRemoved
|
||||
from ...models.event_message_part_updated import EventMessagePartUpdated
|
||||
from ...models.event_message_removed import EventMessageRemoved
|
||||
from ...models.event_message_updated import EventMessageUpdated
|
||||
from ...models.event_permission_replied import EventPermissionReplied
|
||||
from ...models.event_permission_updated import EventPermissionUpdated
|
||||
from ...models.event_server_connected import EventServerConnected
|
||||
from ...models.event_session_compacted import EventSessionCompacted
|
||||
from ...models.event_session_deleted import EventSessionDeleted
|
||||
from ...models.event_session_error import EventSessionError
|
||||
from ...models.event_session_idle import EventSessionIdle
|
||||
from ...models.event_session_updated import EventSessionUpdated
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/event",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
if response.status_code == 200:
|
||||
|
||||
def _parse_response_200(
|
||||
data: object,
|
||||
) -> Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]:
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_0 = EventInstallationUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_0
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_1 = EventLspClientDiagnostics.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_1
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_2 = EventMessageUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_2
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_3 = EventMessageRemoved.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_3
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_4 = EventMessagePartUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_4
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_5 = EventMessagePartRemoved.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_5
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_6 = EventSessionCompacted.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_6
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_7 = EventPermissionUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_7
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_8 = EventPermissionReplied.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_8
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_9 = EventFileEdited.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_9
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_10 = EventSessionIdle.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_10
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_11 = EventSessionUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_11
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_12 = EventSessionDeleted.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_12
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_13 = EventSessionError.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_13
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_14 = EventFileWatcherUpdated.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_14
|
||||
except: # noqa: E722
|
||||
pass
|
||||
try:
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_15 = EventServerConnected.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_15
|
||||
except: # noqa: E722
|
||||
pass
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
componentsschemas_event_type_16 = EventIdeInstalled.from_dict(data)
|
||||
|
||||
return componentsschemas_event_type_16
|
||||
|
||||
response_200 = _parse_response_200(response.text)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
"""Get events
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Union['EventFileEdited', 'EventFileWatcherUpdated', 'EventIdeInstalled', 'EventInstallationUpdated', 'EventLspClientDiagnostics', 'EventMessagePartRemoved', 'EventMessagePartUpdated', 'EventMessageRemoved', 'EventMessageUpdated', 'EventPermissionReplied', 'EventPermissionUpdated', 'EventServerConnected', 'EventSessionCompacted', 'EventSessionDeleted', 'EventSessionError', 'EventSessionIdle', 'EventSessionUpdated']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
"""Get events
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Union['EventFileEdited', 'EventFileWatcherUpdated', 'EventIdeInstalled', 'EventInstallationUpdated', 'EventLspClientDiagnostics', 'EventMessagePartRemoved', 'EventMessagePartUpdated', 'EventMessageRemoved', 'EventMessageUpdated', 'EventPermissionReplied', 'EventPermissionUpdated', 'EventServerConnected', 'EventSessionCompacted', 'EventSessionDeleted', 'EventSessionError', 'EventSessionIdle', 'EventSessionUpdated']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
"""Get events
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Union['EventFileEdited', 'EventFileWatcherUpdated', 'EventIdeInstalled', 'EventInstallationUpdated', 'EventLspClientDiagnostics', 'EventMessagePartRemoved', 'EventMessagePartUpdated', 'EventMessageRemoved', 'EventMessageUpdated', 'EventPermissionReplied', 'EventPermissionUpdated', 'EventServerConnected', 'EventSessionCompacted', 'EventSessionDeleted', 'EventSessionError', 'EventSessionIdle', 'EventSessionUpdated']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[
|
||||
Union[
|
||||
"EventFileEdited",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventIdeInstalled",
|
||||
"EventInstallationUpdated",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageUpdated",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionError",
|
||||
"EventSessionIdle",
|
||||
"EventSessionUpdated",
|
||||
]
|
||||
]:
|
||||
"""Get events
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Union['EventFileEdited', 'EventFileWatcherUpdated', 'EventIdeInstalled', 'EventInstallationUpdated', 'EventLspClientDiagnostics', 'EventMessagePartRemoved', 'EventMessagePartUpdated', 'EventMessageRemoved', 'EventMessageUpdated', 'EventPermissionReplied', 'EventPermissionUpdated', 'EventServerConnected', 'EventSessionCompacted', 'EventSessionDeleted', 'EventSessionError', 'EventSessionIdle', 'EventSessionUpdated']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
160
packages/sdk/python/src/opencode_ai/api/default/file_status.py
Normal file
160
packages/sdk/python/src/opencode_ai/api/default/file_status.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.file import File
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/file/status",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[list["File"]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = []
|
||||
_response_200 = response.json()
|
||||
for response_200_item_data in _response_200:
|
||||
response_200_item = File.from_dict(response_200_item_data)
|
||||
|
||||
response_200.append(response_200_item)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[list["File"]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["File"]]:
|
||||
"""Get file status
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['File']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["File"]]:
|
||||
"""Get file status
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['File']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["File"]]:
|
||||
"""Get file status
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['File']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["File"]]:
|
||||
"""Get file status
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['File']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
155
packages/sdk/python/src/opencode_ai/api/default/path_get.py
Normal file
155
packages/sdk/python/src/opencode_ai/api/default/path_get.py
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.path import Path
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/path",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Path]:
|
||||
if response.status_code == 200:
|
||||
response_200 = Path.from_dict(response.json())
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Path]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Path]:
|
||||
"""Get the current path
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Path]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Path]:
|
||||
"""Get the current path
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Path
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Path]:
|
||||
"""Get the current path
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Path]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Path]:
|
||||
"""Get the current path
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Path
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.project import Project
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/project/current",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Project]:
|
||||
if response.status_code == 200:
|
||||
response_200 = Project.from_dict(response.json())
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Project]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Project]:
|
||||
"""Get the current project
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Project]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Project]:
|
||||
"""Get the current project
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Project
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Project]:
|
||||
"""Get the current project
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Project]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Project]:
|
||||
"""Get the current project
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Project
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
164
packages/sdk/python/src/opencode_ai/api/default/project_list.py
Normal file
164
packages/sdk/python/src/opencode_ai/api/default/project_list.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.project import Project
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/project",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Optional[list["Project"]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = []
|
||||
_response_200 = response.json()
|
||||
for response_200_item_data in _response_200:
|
||||
response_200_item = Project.from_dict(response_200_item_data)
|
||||
|
||||
response_200.append(response_200_item)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Response[list["Project"]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Project"]]:
|
||||
"""List all projects
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Project']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Project"]]:
|
||||
"""List all projects
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Project']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Project"]]:
|
||||
"""List all projects
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Project']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Project"]]:
|
||||
"""List all projects
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Project']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
164
packages/sdk/python/src/opencode_ai/api/default/session_list.py
Normal file
164
packages/sdk/python/src/opencode_ai/api/default/session_list.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.session import Session
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/session",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Optional[list["Session"]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = []
|
||||
_response_200 = response.json()
|
||||
for response_200_item_data in _response_200:
|
||||
response_200_item = Session.from_dict(response_200_item_data)
|
||||
|
||||
response_200.append(response_200_item)
|
||||
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Response[list["Session"]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Session"]]:
|
||||
"""List all sessions
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Session']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Session"]]:
|
||||
"""List all sessions
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Session']
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[list["Session"]]:
|
||||
"""List all sessions
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[list['Session']]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[list["Session"]]:
|
||||
"""List all sessions
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
list['Session']
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
164
packages/sdk/python/src/opencode_ai/api/default/tool_ids.py
Normal file
164
packages/sdk/python/src/opencode_ai/api/default/tool_ids.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...models.error import Error
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "get",
|
||||
"url": "/experimental/tool/ids",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Optional[Union[Error, list[str]]]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(list[str], response.json())
|
||||
|
||||
return response_200
|
||||
|
||||
if response.status_code == 400:
|
||||
response_400 = Error.from_dict(response.json())
|
||||
|
||||
return response_400
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(
|
||||
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
||||
) -> Response[Union[Error, list[str]]]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Union[Error, list[str]]]:
|
||||
"""List all tool IDs (including built-in and dynamically registered)
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Union[Error, list[str]]]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Union[Error, list[str]]]:
|
||||
"""List all tool IDs (including built-in and dynamically registered)
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Union[Error, list[str]]
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[Union[Error, list[str]]]:
|
||||
"""List all tool IDs (including built-in and dynamically registered)
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[Union[Error, list[str]]]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[Union[Error, list[str]]]:
|
||||
"""List all tool IDs (including built-in and dynamically registered)
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Union[Error, list[str]]
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/clear-prompt",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Clear the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Clear the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Clear the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Clear the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
153
packages/sdk/python/src/opencode_ai/api/default/tui_open_help.py
Normal file
153
packages/sdk/python/src/opencode_ai/api/default/tui_open_help.py
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/open-help",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the help dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the help dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the help dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the help dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/open-models",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the model dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the model dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the model dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the model dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/open-sessions",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the session dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the session dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the session dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the session dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/open-themes",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the theme dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the theme dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Open the theme dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Open the theme dialog
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import errors
|
||||
from ...client import AuthenticatedClient, Client
|
||||
from ...types import UNSET, Response, Unset
|
||||
|
||||
|
||||
def _get_kwargs(
|
||||
*,
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> dict[str, Any]:
|
||||
params: dict[str, Any] = {}
|
||||
|
||||
params["directory"] = directory
|
||||
|
||||
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
||||
|
||||
_kwargs: dict[str, Any] = {
|
||||
"method": "post",
|
||||
"url": "/tui/submit-prompt",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
return _kwargs
|
||||
|
||||
|
||||
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[bool]:
|
||||
if response.status_code == 200:
|
||||
response_200 = cast(bool, response.json())
|
||||
return response_200
|
||||
|
||||
if client.raise_on_unexpected_status:
|
||||
raise errors.UnexpectedStatus(response.status_code, response.content)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[bool]:
|
||||
return Response(
|
||||
status_code=HTTPStatus(response.status_code),
|
||||
content=response.content,
|
||||
headers=response.headers,
|
||||
parsed=_parse_response(client=client, response=response),
|
||||
)
|
||||
|
||||
|
||||
def sync_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Submit the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = client.get_httpx_client().request(
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
def sync(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Submit the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return sync_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
).parsed
|
||||
|
||||
|
||||
async def asyncio_detailed(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Response[bool]:
|
||||
"""Submit the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
Response[bool]
|
||||
"""
|
||||
|
||||
kwargs = _get_kwargs(
|
||||
directory=directory,
|
||||
)
|
||||
|
||||
response = await client.get_async_httpx_client().request(**kwargs)
|
||||
|
||||
return _build_response(client=client, response=response)
|
||||
|
||||
|
||||
async def asyncio(
|
||||
*,
|
||||
client: Union[AuthenticatedClient, Client],
|
||||
directory: Union[Unset, str] = UNSET,
|
||||
) -> Optional[bool]:
|
||||
"""Submit the prompt
|
||||
|
||||
Args:
|
||||
directory (Union[Unset, str]):
|
||||
|
||||
Raises:
|
||||
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
||||
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
|
||||
return (
|
||||
await asyncio_detailed(
|
||||
client=client,
|
||||
directory=directory,
|
||||
)
|
||||
).parsed
|
||||
268
packages/sdk/python/src/opencode_ai/client.py
Normal file
268
packages/sdk/python/src/opencode_ai/client.py
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
import ssl
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import httpx
|
||||
from attrs import define, evolve, field
|
||||
|
||||
|
||||
@define
|
||||
class Client:
|
||||
"""A class for keeping track of data related to the API
|
||||
|
||||
The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
|
||||
|
||||
``base_url``: The base URL for the API, all requests are made to a relative path to this URL
|
||||
|
||||
``cookies``: A dictionary of cookies to be sent with every request
|
||||
|
||||
``headers``: A dictionary of headers to be sent with every request
|
||||
|
||||
``timeout``: The maximum amount of a time a request can take. API functions will raise
|
||||
httpx.TimeoutException if this is exceeded.
|
||||
|
||||
``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
|
||||
but can be set to False for testing purposes.
|
||||
|
||||
``follow_redirects``: Whether or not to follow redirects. Default value is False.
|
||||
|
||||
``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
|
||||
|
||||
|
||||
Attributes:
|
||||
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
|
||||
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
|
||||
argument to the constructor.
|
||||
"""
|
||||
|
||||
raise_on_unexpected_status: bool = field(default=False, kw_only=True)
|
||||
_base_url: str = field(alias="base_url")
|
||||
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
|
||||
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
|
||||
_timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
|
||||
_verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
|
||||
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
|
||||
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
|
||||
_client: Optional[httpx.Client] = field(default=None, init=False)
|
||||
_async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)
|
||||
|
||||
def with_headers(self, headers: dict[str, str]) -> "Client":
|
||||
"""Get a new client matching this one with additional headers"""
|
||||
if self._client is not None:
|
||||
self._client.headers.update(headers)
|
||||
if self._async_client is not None:
|
||||
self._async_client.headers.update(headers)
|
||||
return evolve(self, headers={**self._headers, **headers})
|
||||
|
||||
def with_cookies(self, cookies: dict[str, str]) -> "Client":
|
||||
"""Get a new client matching this one with additional cookies"""
|
||||
if self._client is not None:
|
||||
self._client.cookies.update(cookies)
|
||||
if self._async_client is not None:
|
||||
self._async_client.cookies.update(cookies)
|
||||
return evolve(self, cookies={**self._cookies, **cookies})
|
||||
|
||||
def with_timeout(self, timeout: httpx.Timeout) -> "Client":
|
||||
"""Get a new client matching this one with a new timeout (in seconds)"""
|
||||
if self._client is not None:
|
||||
self._client.timeout = timeout
|
||||
if self._async_client is not None:
|
||||
self._async_client.timeout = timeout
|
||||
return evolve(self, timeout=timeout)
|
||||
|
||||
def set_httpx_client(self, client: httpx.Client) -> "Client":
|
||||
"""Manually set the underlying httpx.Client
|
||||
|
||||
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
||||
"""
|
||||
self._client = client
|
||||
return self
|
||||
|
||||
def get_httpx_client(self) -> httpx.Client:
|
||||
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
|
||||
if self._client is None:
|
||||
self._client = httpx.Client(
|
||||
base_url=self._base_url,
|
||||
cookies=self._cookies,
|
||||
headers=self._headers,
|
||||
timeout=self._timeout,
|
||||
verify=self._verify_ssl,
|
||||
follow_redirects=self._follow_redirects,
|
||||
**self._httpx_args,
|
||||
)
|
||||
return self._client
|
||||
|
||||
def __enter__(self) -> "Client":
|
||||
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
|
||||
self.get_httpx_client().__enter__()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
|
||||
self.get_httpx_client().__exit__(*args, **kwargs)
|
||||
|
||||
def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client":
|
||||
"""Manually the underlying httpx.AsyncClient
|
||||
|
||||
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
||||
"""
|
||||
self._async_client = async_client
|
||||
return self
|
||||
|
||||
def get_async_httpx_client(self) -> httpx.AsyncClient:
|
||||
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
|
||||
if self._async_client is None:
|
||||
self._async_client = httpx.AsyncClient(
|
||||
base_url=self._base_url,
|
||||
cookies=self._cookies,
|
||||
headers=self._headers,
|
||||
timeout=self._timeout,
|
||||
verify=self._verify_ssl,
|
||||
follow_redirects=self._follow_redirects,
|
||||
**self._httpx_args,
|
||||
)
|
||||
return self._async_client
|
||||
|
||||
async def __aenter__(self) -> "Client":
|
||||
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
|
||||
await self.get_async_httpx_client().__aenter__()
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
|
||||
await self.get_async_httpx_client().__aexit__(*args, **kwargs)
|
||||
|
||||
|
||||
@define
|
||||
class AuthenticatedClient:
|
||||
"""A Client which has been authenticated for use on secured endpoints
|
||||
|
||||
The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
|
||||
|
||||
``base_url``: The base URL for the API, all requests are made to a relative path to this URL
|
||||
|
||||
``cookies``: A dictionary of cookies to be sent with every request
|
||||
|
||||
``headers``: A dictionary of headers to be sent with every request
|
||||
|
||||
``timeout``: The maximum amount of a time a request can take. API functions will raise
|
||||
httpx.TimeoutException if this is exceeded.
|
||||
|
||||
``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
|
||||
but can be set to False for testing purposes.
|
||||
|
||||
``follow_redirects``: Whether or not to follow redirects. Default value is False.
|
||||
|
||||
``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
|
||||
|
||||
|
||||
Attributes:
|
||||
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
|
||||
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
|
||||
argument to the constructor.
|
||||
token: The token to use for authentication
|
||||
prefix: The prefix to use for the Authorization header
|
||||
auth_header_name: The name of the Authorization header
|
||||
"""
|
||||
|
||||
raise_on_unexpected_status: bool = field(default=False, kw_only=True)
|
||||
_base_url: str = field(alias="base_url")
|
||||
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
|
||||
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
|
||||
_timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
|
||||
_verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
|
||||
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
|
||||
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
|
||||
_client: Optional[httpx.Client] = field(default=None, init=False)
|
||||
_async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)
|
||||
|
||||
token: str
|
||||
prefix: str = "Bearer"
|
||||
auth_header_name: str = "Authorization"
|
||||
|
||||
def with_headers(self, headers: dict[str, str]) -> "AuthenticatedClient":
|
||||
"""Get a new client matching this one with additional headers"""
|
||||
if self._client is not None:
|
||||
self._client.headers.update(headers)
|
||||
if self._async_client is not None:
|
||||
self._async_client.headers.update(headers)
|
||||
return evolve(self, headers={**self._headers, **headers})
|
||||
|
||||
def with_cookies(self, cookies: dict[str, str]) -> "AuthenticatedClient":
|
||||
"""Get a new client matching this one with additional cookies"""
|
||||
if self._client is not None:
|
||||
self._client.cookies.update(cookies)
|
||||
if self._async_client is not None:
|
||||
self._async_client.cookies.update(cookies)
|
||||
return evolve(self, cookies={**self._cookies, **cookies})
|
||||
|
||||
def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
|
||||
"""Get a new client matching this one with a new timeout (in seconds)"""
|
||||
if self._client is not None:
|
||||
self._client.timeout = timeout
|
||||
if self._async_client is not None:
|
||||
self._async_client.timeout = timeout
|
||||
return evolve(self, timeout=timeout)
|
||||
|
||||
def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
|
||||
"""Manually set the underlying httpx.Client
|
||||
|
||||
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
||||
"""
|
||||
self._client = client
|
||||
return self
|
||||
|
||||
def get_httpx_client(self) -> httpx.Client:
|
||||
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
|
||||
if self._client is None:
|
||||
self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
|
||||
self._client = httpx.Client(
|
||||
base_url=self._base_url,
|
||||
cookies=self._cookies,
|
||||
headers=self._headers,
|
||||
timeout=self._timeout,
|
||||
verify=self._verify_ssl,
|
||||
follow_redirects=self._follow_redirects,
|
||||
**self._httpx_args,
|
||||
)
|
||||
return self._client
|
||||
|
||||
def __enter__(self) -> "AuthenticatedClient":
|
||||
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
|
||||
self.get_httpx_client().__enter__()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
|
||||
self.get_httpx_client().__exit__(*args, **kwargs)
|
||||
|
||||
def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient":
|
||||
"""Manually the underlying httpx.AsyncClient
|
||||
|
||||
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
||||
"""
|
||||
self._async_client = async_client
|
||||
return self
|
||||
|
||||
def get_async_httpx_client(self) -> httpx.AsyncClient:
|
||||
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
|
||||
if self._async_client is None:
|
||||
self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
|
||||
self._async_client = httpx.AsyncClient(
|
||||
base_url=self._base_url,
|
||||
cookies=self._cookies,
|
||||
headers=self._headers,
|
||||
timeout=self._timeout,
|
||||
verify=self._verify_ssl,
|
||||
follow_redirects=self._follow_redirects,
|
||||
**self._httpx_args,
|
||||
)
|
||||
return self._async_client
|
||||
|
||||
async def __aenter__(self) -> "AuthenticatedClient":
|
||||
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
|
||||
await self.get_async_httpx_client().__aenter__()
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
|
||||
await self.get_async_httpx_client().__aexit__(*args, **kwargs)
|
||||
16
packages/sdk/python/src/opencode_ai/errors.py
Normal file
16
packages/sdk/python/src/opencode_ai/errors.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
"""Contains shared errors types that can be raised from API functions"""
|
||||
|
||||
|
||||
class UnexpectedStatus(Exception):
|
||||
"""Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True"""
|
||||
|
||||
def __init__(self, status_code: int, content: bytes):
|
||||
self.status_code = status_code
|
||||
self.content = content
|
||||
|
||||
super().__init__(
|
||||
f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}"
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["UnexpectedStatus"]
|
||||
186
packages/sdk/python/src/opencode_ai/extras.py
Normal file
186
packages/sdk/python/src/opencode_ai/extras.py
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from typing import AsyncIterator, Dict, Iterator, Optional
|
||||
|
||||
import httpx
|
||||
|
||||
from .api.default import (
|
||||
app_agents,
|
||||
command_list,
|
||||
config_get,
|
||||
config_providers,
|
||||
file_status,
|
||||
path_get,
|
||||
project_current,
|
||||
project_list,
|
||||
session_list,
|
||||
tool_ids,
|
||||
)
|
||||
from .client import Client
|
||||
from .types import UNSET, Unset
|
||||
|
||||
|
||||
class OpenCodeClient:
|
||||
"""High-level convenience wrapper around the generated Client.
|
||||
|
||||
Provides sensible defaults and a couple of helper methods, with optional retries.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str = "http://localhost:4096",
|
||||
*,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
verify_ssl: bool | str | httpx.URLTypes | None = True,
|
||||
token: Optional[str] = None,
|
||||
auth_header_name: str = "Authorization",
|
||||
auth_prefix: str = "Bearer",
|
||||
retries: int = 0,
|
||||
backoff_factor: float = 0.5,
|
||||
status_forcelist: tuple[int, ...] = (429, 500, 502, 503, 504),
|
||||
) -> None:
|
||||
httpx_timeout = None if timeout is None else httpx.Timeout(timeout)
|
||||
all_headers = dict(headers or {})
|
||||
if token:
|
||||
all_headers[auth_header_name] = f"{auth_prefix} {token}".strip()
|
||||
self._client = Client(
|
||||
base_url=base_url,
|
||||
headers=all_headers,
|
||||
timeout=httpx_timeout,
|
||||
verify_ssl=verify_ssl if isinstance(verify_ssl, bool) else True,
|
||||
)
|
||||
self._retries = max(0, int(retries))
|
||||
self._backoff = float(backoff_factor)
|
||||
self._status_forcelist = set(status_forcelist)
|
||||
|
||||
@property
|
||||
def client(self) -> Client:
|
||||
return self._client
|
||||
|
||||
# ---- Internal retry helper ----
|
||||
|
||||
def _call_with_retries(self, fn, *args, **kwargs):
|
||||
attempt = 0
|
||||
while True:
|
||||
try:
|
||||
return fn(*args, **kwargs)
|
||||
except httpx.RequestError:
|
||||
pass
|
||||
except httpx.HTTPStatusError as e:
|
||||
if e.response is None or e.response.status_code not in self._status_forcelist:
|
||||
raise
|
||||
if attempt >= self._retries:
|
||||
# re-raise last exception if we have one
|
||||
raise
|
||||
sleep = self._backoff * (2**attempt)
|
||||
time.sleep(sleep)
|
||||
attempt += 1
|
||||
|
||||
# ---- Convenience wrappers over generated endpoints ----
|
||||
|
||||
def list_sessions(self, *, directory: str | Unset = UNSET):
|
||||
"""Return sessions in the current project.
|
||||
|
||||
Wraps GET /session. Pass `directory` to target a specific project/directory if needed.
|
||||
"""
|
||||
return self._call_with_retries(session_list.sync, client=self._client, directory=directory)
|
||||
|
||||
def get_config(self, *, directory: str | Unset = UNSET):
|
||||
"""Return opencode configuration for the current project (GET /config)."""
|
||||
return self._call_with_retries(config_get.sync, client=self._client, directory=directory)
|
||||
|
||||
def list_agents(self, *, directory: str | Unset = UNSET):
|
||||
"""List configured agents (GET /agent)."""
|
||||
return self._call_with_retries(app_agents.sync, client=self._client, directory=directory)
|
||||
|
||||
def list_projects(self, *, directory: str | Unset = UNSET):
|
||||
"""List known projects (GET /project)."""
|
||||
return self._call_with_retries(project_list.sync, client=self._client, directory=directory)
|
||||
|
||||
def current_project(self, *, directory: str | Unset = UNSET):
|
||||
"""Return current project (GET /project/current)."""
|
||||
return self._call_with_retries(project_current.sync, client=self._client, directory=directory)
|
||||
|
||||
def file_status(self, *, directory: str | Unset = UNSET):
|
||||
"""Return file status list (GET /file/status)."""
|
||||
return self._call_with_retries(file_status.sync, client=self._client, directory=directory)
|
||||
|
||||
def get_path(self, *, directory: str | Unset = UNSET):
|
||||
"""Return opencode path info (GET /path)."""
|
||||
return self._call_with_retries(path_get.sync, client=self._client, directory=directory)
|
||||
|
||||
def config_providers(self, *, directory: str | Unset = UNSET):
|
||||
"""Return configured providers (GET /config/providers)."""
|
||||
return self._call_with_retries(config_providers.sync, client=self._client, directory=directory)
|
||||
|
||||
def tool_ids(self, *, directory: str | Unset = UNSET):
|
||||
"""Return tool identifiers for a provider/model pair (GET /experimental/tool)."""
|
||||
return self._call_with_retries(tool_ids.sync, client=self._client, directory=directory)
|
||||
|
||||
def list_commands(self, *, directory: str | Unset = UNSET):
|
||||
"""List commands (GET /command)."""
|
||||
return self._call_with_retries(command_list.sync, client=self._client, directory=directory)
|
||||
|
||||
# ---- Server-Sent Events (SSE) streaming ----
|
||||
|
||||
def subscribe_events(self, *, directory: str | Unset = UNSET) -> Iterator[dict]:
|
||||
"""Subscribe to /event SSE endpoint and yield parsed JSON events.
|
||||
|
||||
This is a blocking generator which yields one event dict per message.
|
||||
"""
|
||||
client = self._client.get_httpx_client()
|
||||
params: dict[str, str] = {}
|
||||
if directory is not UNSET and directory is not None:
|
||||
params["directory"] = str(directory)
|
||||
with client.stream("GET", "/event", headers={"Accept": "text/event-stream"}, params=params) as r:
|
||||
r.raise_for_status()
|
||||
buf = ""
|
||||
for line_bytes in r.iter_lines():
|
||||
line = line_bytes.decode("utf-8") if isinstance(line_bytes, (bytes, bytearray)) else str(line_bytes)
|
||||
if line.startswith(":"):
|
||||
# comment/heartbeat
|
||||
continue
|
||||
if line == "":
|
||||
if buf:
|
||||
# end of event
|
||||
for part in buf.split("\n"):
|
||||
if part.startswith("data:"):
|
||||
data = part[5:].strip()
|
||||
if data:
|
||||
try:
|
||||
yield httpx._models.jsonlib.loads(data) # type: ignore[attr-defined]
|
||||
except Exception:
|
||||
# fall back: skip malformed
|
||||
pass
|
||||
buf = ""
|
||||
continue
|
||||
buf += line + "\n"
|
||||
|
||||
async def subscribe_events_async(self, *, directory: str | Unset = UNSET) -> AsyncIterator[dict]:
|
||||
"""Async variant of subscribe_events using httpx.AsyncClient."""
|
||||
aclient = self._client.get_async_httpx_client()
|
||||
params: dict[str, str] = {}
|
||||
if directory is not UNSET and directory is not None:
|
||||
params["directory"] = str(directory)
|
||||
async with aclient.stream("GET", "/event", headers={"Accept": "text/event-stream"}, params=params) as r:
|
||||
r.raise_for_status()
|
||||
buf = ""
|
||||
async for line_bytes in r.aiter_lines():
|
||||
line = line_bytes
|
||||
if line.startswith(":"):
|
||||
continue
|
||||
if line == "":
|
||||
if buf:
|
||||
for part in buf.split("\n"):
|
||||
if part.startswith("data:"):
|
||||
data = part[5:].strip()
|
||||
if data:
|
||||
try:
|
||||
yield httpx._models.jsonlib.loads(data) # type: ignore[attr-defined]
|
||||
except Exception:
|
||||
pass
|
||||
buf = ""
|
||||
continue
|
||||
buf += line + "\n"
|
||||
367
packages/sdk/python/src/opencode_ai/models/__init__.py
Normal file
367
packages/sdk/python/src/opencode_ai/models/__init__.py
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
"""Contains all the data models used in inputs/outputs"""
|
||||
|
||||
from .agent import Agent
|
||||
from .agent_config import AgentConfig
|
||||
from .agent_config_permission import AgentConfigPermission
|
||||
from .agent_config_permission_bash_type_1 import AgentConfigPermissionBashType1
|
||||
from .agent_config_tools import AgentConfigTools
|
||||
from .agent_model import AgentModel
|
||||
from .agent_options import AgentOptions
|
||||
from .agent_part import AgentPart
|
||||
from .agent_part_input import AgentPartInput
|
||||
from .agent_part_input_source import AgentPartInputSource
|
||||
from .agent_part_source import AgentPartSource
|
||||
from .agent_permission import AgentPermission
|
||||
from .agent_permission_bash import AgentPermissionBash
|
||||
from .agent_tools import AgentTools
|
||||
from .api_auth import ApiAuth
|
||||
from .assistant_message import AssistantMessage
|
||||
from .assistant_message_path import AssistantMessagePath
|
||||
from .assistant_message_time import AssistantMessageTime
|
||||
from .assistant_message_tokens import AssistantMessageTokens
|
||||
from .assistant_message_tokens_cache import AssistantMessageTokensCache
|
||||
from .command import Command
|
||||
from .config import Config
|
||||
from .config_agent import ConfigAgent
|
||||
from .config_command import ConfigCommand
|
||||
from .config_command_additional_property import ConfigCommandAdditionalProperty
|
||||
from .config_experimental import ConfigExperimental
|
||||
from .config_experimental_hook import ConfigExperimentalHook
|
||||
from .config_experimental_hook_file_edited import ConfigExperimentalHookFileEdited
|
||||
from .config_experimental_hook_file_edited_additional_property_item import (
|
||||
ConfigExperimentalHookFileEditedAdditionalPropertyItem,
|
||||
)
|
||||
from .config_experimental_hook_file_edited_additional_property_item_environment import (
|
||||
ConfigExperimentalHookFileEditedAdditionalPropertyItemEnvironment,
|
||||
)
|
||||
from .config_experimental_hook_session_completed_item import ConfigExperimentalHookSessionCompletedItem
|
||||
from .config_experimental_hook_session_completed_item_environment import (
|
||||
ConfigExperimentalHookSessionCompletedItemEnvironment,
|
||||
)
|
||||
from .config_formatter import ConfigFormatter
|
||||
from .config_formatter_additional_property import ConfigFormatterAdditionalProperty
|
||||
from .config_formatter_additional_property_environment import ConfigFormatterAdditionalPropertyEnvironment
|
||||
from .config_lsp import ConfigLsp
|
||||
from .config_lsp_additional_property_type_0 import ConfigLspAdditionalPropertyType0
|
||||
from .config_lsp_additional_property_type_1 import ConfigLspAdditionalPropertyType1
|
||||
from .config_lsp_additional_property_type_1_env import ConfigLspAdditionalPropertyType1Env
|
||||
from .config_lsp_additional_property_type_1_initialization import ConfigLspAdditionalPropertyType1Initialization
|
||||
from .config_mcp import ConfigMcp
|
||||
from .config_mode import ConfigMode
|
||||
from .config_permission import ConfigPermission
|
||||
from .config_permission_bash_type_1 import ConfigPermissionBashType1
|
||||
from .config_provider import ConfigProvider
|
||||
from .config_provider_additional_property import ConfigProviderAdditionalProperty
|
||||
from .config_provider_additional_property_models import ConfigProviderAdditionalPropertyModels
|
||||
from .config_provider_additional_property_models_additional_property import (
|
||||
ConfigProviderAdditionalPropertyModelsAdditionalProperty,
|
||||
)
|
||||
from .config_provider_additional_property_models_additional_property_cost import (
|
||||
ConfigProviderAdditionalPropertyModelsAdditionalPropertyCost,
|
||||
)
|
||||
from .config_provider_additional_property_models_additional_property_limit import (
|
||||
ConfigProviderAdditionalPropertyModelsAdditionalPropertyLimit,
|
||||
)
|
||||
from .config_provider_additional_property_models_additional_property_options import (
|
||||
ConfigProviderAdditionalPropertyModelsAdditionalPropertyOptions,
|
||||
)
|
||||
from .config_provider_additional_property_models_additional_property_provider import (
|
||||
ConfigProviderAdditionalPropertyModelsAdditionalPropertyProvider,
|
||||
)
|
||||
from .config_provider_additional_property_options import ConfigProviderAdditionalPropertyOptions
|
||||
from .config_providers_response_200 import ConfigProvidersResponse200
|
||||
from .config_providers_response_200_default import ConfigProvidersResponse200Default
|
||||
from .config_share import ConfigShare
|
||||
from .config_tools import ConfigTools
|
||||
from .config_tui import ConfigTui
|
||||
from .config_watcher import ConfigWatcher
|
||||
from .error import Error
|
||||
from .error_data import ErrorData
|
||||
from .event_file_edited import EventFileEdited
|
||||
from .event_file_edited_properties import EventFileEditedProperties
|
||||
from .event_file_watcher_updated import EventFileWatcherUpdated
|
||||
from .event_file_watcher_updated_properties import EventFileWatcherUpdatedProperties
|
||||
from .event_ide_installed import EventIdeInstalled
|
||||
from .event_ide_installed_properties import EventIdeInstalledProperties
|
||||
from .event_installation_updated import EventInstallationUpdated
|
||||
from .event_installation_updated_properties import EventInstallationUpdatedProperties
|
||||
from .event_lsp_client_diagnostics import EventLspClientDiagnostics
|
||||
from .event_lsp_client_diagnostics_properties import EventLspClientDiagnosticsProperties
|
||||
from .event_message_part_removed import EventMessagePartRemoved
|
||||
from .event_message_part_removed_properties import EventMessagePartRemovedProperties
|
||||
from .event_message_part_updated import EventMessagePartUpdated
|
||||
from .event_message_part_updated_properties import EventMessagePartUpdatedProperties
|
||||
from .event_message_removed import EventMessageRemoved
|
||||
from .event_message_removed_properties import EventMessageRemovedProperties
|
||||
from .event_message_updated import EventMessageUpdated
|
||||
from .event_message_updated_properties import EventMessageUpdatedProperties
|
||||
from .event_permission_replied import EventPermissionReplied
|
||||
from .event_permission_replied_properties import EventPermissionRepliedProperties
|
||||
from .event_permission_updated import EventPermissionUpdated
|
||||
from .event_server_connected import EventServerConnected
|
||||
from .event_server_connected_properties import EventServerConnectedProperties
|
||||
from .event_session_compacted import EventSessionCompacted
|
||||
from .event_session_compacted_properties import EventSessionCompactedProperties
|
||||
from .event_session_deleted import EventSessionDeleted
|
||||
from .event_session_deleted_properties import EventSessionDeletedProperties
|
||||
from .event_session_error import EventSessionError
|
||||
from .event_session_error_properties import EventSessionErrorProperties
|
||||
from .event_session_idle import EventSessionIdle
|
||||
from .event_session_idle_properties import EventSessionIdleProperties
|
||||
from .event_session_updated import EventSessionUpdated
|
||||
from .event_session_updated_properties import EventSessionUpdatedProperties
|
||||
from .file import File
|
||||
from .file_content import FileContent
|
||||
from .file_content_patch import FileContentPatch
|
||||
from .file_content_patch_hunks_item import FileContentPatchHunksItem
|
||||
from .file_node import FileNode
|
||||
from .file_node_type import FileNodeType
|
||||
from .file_part import FilePart
|
||||
from .file_part_input import FilePartInput
|
||||
from .file_part_source_text import FilePartSourceText
|
||||
from .file_source import FileSource
|
||||
from .file_status import FileStatus
|
||||
from .keybinds_config import KeybindsConfig
|
||||
from .layout_config import LayoutConfig
|
||||
from .mcp_local_config import McpLocalConfig
|
||||
from .mcp_local_config_environment import McpLocalConfigEnvironment
|
||||
from .mcp_remote_config import McpRemoteConfig
|
||||
from .mcp_remote_config_headers import McpRemoteConfigHeaders
|
||||
from .message_aborted_error import MessageAbortedError
|
||||
from .message_aborted_error_data import MessageAbortedErrorData
|
||||
from .message_output_length_error import MessageOutputLengthError
|
||||
from .message_output_length_error_data import MessageOutputLengthErrorData
|
||||
from .model import Model
|
||||
from .model_cost import ModelCost
|
||||
from .model_limit import ModelLimit
|
||||
from .model_options import ModelOptions
|
||||
from .model_provider import ModelProvider
|
||||
from .o_auth import OAuth
|
||||
from .patch_part import PatchPart
|
||||
from .path import Path
|
||||
from .permission import Permission
|
||||
from .permission_metadata import PermissionMetadata
|
||||
from .permission_time import PermissionTime
|
||||
from .project import Project
|
||||
from .project_time import ProjectTime
|
||||
from .provider import Provider
|
||||
from .provider_auth_error import ProviderAuthError
|
||||
from .provider_auth_error_data import ProviderAuthErrorData
|
||||
from .provider_models import ProviderModels
|
||||
from .range_ import Range
|
||||
from .range_end import RangeEnd
|
||||
from .range_start import RangeStart
|
||||
from .reasoning_part import ReasoningPart
|
||||
from .reasoning_part_metadata import ReasoningPartMetadata
|
||||
from .reasoning_part_time import ReasoningPartTime
|
||||
from .session import Session
|
||||
from .session_revert import SessionRevert
|
||||
from .session_share import SessionShare
|
||||
from .session_time import SessionTime
|
||||
from .snapshot_part import SnapshotPart
|
||||
from .step_finish_part import StepFinishPart
|
||||
from .step_finish_part_tokens import StepFinishPartTokens
|
||||
from .step_finish_part_tokens_cache import StepFinishPartTokensCache
|
||||
from .step_start_part import StepStartPart
|
||||
from .symbol import Symbol
|
||||
from .symbol_location import SymbolLocation
|
||||
from .symbol_source import SymbolSource
|
||||
from .text_part import TextPart
|
||||
from .text_part_input import TextPartInput
|
||||
from .text_part_input_time import TextPartInputTime
|
||||
from .text_part_time import TextPartTime
|
||||
from .tool_list_item import ToolListItem
|
||||
from .tool_part import ToolPart
|
||||
from .tool_state_completed import ToolStateCompleted
|
||||
from .tool_state_completed_input import ToolStateCompletedInput
|
||||
from .tool_state_completed_metadata import ToolStateCompletedMetadata
|
||||
from .tool_state_completed_time import ToolStateCompletedTime
|
||||
from .tool_state_error import ToolStateError
|
||||
from .tool_state_error_input import ToolStateErrorInput
|
||||
from .tool_state_error_metadata import ToolStateErrorMetadata
|
||||
from .tool_state_error_time import ToolStateErrorTime
|
||||
from .tool_state_pending import ToolStatePending
|
||||
from .tool_state_running import ToolStateRunning
|
||||
from .tool_state_running_metadata import ToolStateRunningMetadata
|
||||
from .tool_state_running_time import ToolStateRunningTime
|
||||
from .unknown_error import UnknownError
|
||||
from .unknown_error_data import UnknownErrorData
|
||||
from .user_message import UserMessage
|
||||
from .user_message_time import UserMessageTime
|
||||
from .well_known_auth import WellKnownAuth
|
||||
|
||||
__all__ = (
|
||||
"Agent",
|
||||
"AgentConfig",
|
||||
"AgentConfigPermission",
|
||||
"AgentConfigPermissionBashType1",
|
||||
"AgentConfigTools",
|
||||
"AgentModel",
|
||||
"AgentOptions",
|
||||
"AgentPart",
|
||||
"AgentPartInput",
|
||||
"AgentPartInputSource",
|
||||
"AgentPartSource",
|
||||
"AgentPermission",
|
||||
"AgentPermissionBash",
|
||||
"AgentTools",
|
||||
"ApiAuth",
|
||||
"AssistantMessage",
|
||||
"AssistantMessagePath",
|
||||
"AssistantMessageTime",
|
||||
"AssistantMessageTokens",
|
||||
"AssistantMessageTokensCache",
|
||||
"Command",
|
||||
"Config",
|
||||
"ConfigAgent",
|
||||
"ConfigCommand",
|
||||
"ConfigCommandAdditionalProperty",
|
||||
"ConfigExperimental",
|
||||
"ConfigExperimentalHook",
|
||||
"ConfigExperimentalHookFileEdited",
|
||||
"ConfigExperimentalHookFileEditedAdditionalPropertyItem",
|
||||
"ConfigExperimentalHookFileEditedAdditionalPropertyItemEnvironment",
|
||||
"ConfigExperimentalHookSessionCompletedItem",
|
||||
"ConfigExperimentalHookSessionCompletedItemEnvironment",
|
||||
"ConfigFormatter",
|
||||
"ConfigFormatterAdditionalProperty",
|
||||
"ConfigFormatterAdditionalPropertyEnvironment",
|
||||
"ConfigLsp",
|
||||
"ConfigLspAdditionalPropertyType0",
|
||||
"ConfigLspAdditionalPropertyType1",
|
||||
"ConfigLspAdditionalPropertyType1Env",
|
||||
"ConfigLspAdditionalPropertyType1Initialization",
|
||||
"ConfigMcp",
|
||||
"ConfigMode",
|
||||
"ConfigPermission",
|
||||
"ConfigPermissionBashType1",
|
||||
"ConfigProvider",
|
||||
"ConfigProviderAdditionalProperty",
|
||||
"ConfigProviderAdditionalPropertyModels",
|
||||
"ConfigProviderAdditionalPropertyModelsAdditionalProperty",
|
||||
"ConfigProviderAdditionalPropertyModelsAdditionalPropertyCost",
|
||||
"ConfigProviderAdditionalPropertyModelsAdditionalPropertyLimit",
|
||||
"ConfigProviderAdditionalPropertyModelsAdditionalPropertyOptions",
|
||||
"ConfigProviderAdditionalPropertyModelsAdditionalPropertyProvider",
|
||||
"ConfigProviderAdditionalPropertyOptions",
|
||||
"ConfigProvidersResponse200",
|
||||
"ConfigProvidersResponse200Default",
|
||||
"ConfigShare",
|
||||
"ConfigTools",
|
||||
"ConfigTui",
|
||||
"ConfigWatcher",
|
||||
"Error",
|
||||
"ErrorData",
|
||||
"EventFileEdited",
|
||||
"EventFileEditedProperties",
|
||||
"EventFileWatcherUpdated",
|
||||
"EventFileWatcherUpdatedProperties",
|
||||
"EventIdeInstalled",
|
||||
"EventIdeInstalledProperties",
|
||||
"EventInstallationUpdated",
|
||||
"EventInstallationUpdatedProperties",
|
||||
"EventLspClientDiagnostics",
|
||||
"EventLspClientDiagnosticsProperties",
|
||||
"EventMessagePartRemoved",
|
||||
"EventMessagePartRemovedProperties",
|
||||
"EventMessagePartUpdated",
|
||||
"EventMessagePartUpdatedProperties",
|
||||
"EventMessageRemoved",
|
||||
"EventMessageRemovedProperties",
|
||||
"EventMessageUpdated",
|
||||
"EventMessageUpdatedProperties",
|
||||
"EventPermissionReplied",
|
||||
"EventPermissionRepliedProperties",
|
||||
"EventPermissionUpdated",
|
||||
"EventServerConnected",
|
||||
"EventServerConnectedProperties",
|
||||
"EventSessionCompacted",
|
||||
"EventSessionCompactedProperties",
|
||||
"EventSessionDeleted",
|
||||
"EventSessionDeletedProperties",
|
||||
"EventSessionError",
|
||||
"EventSessionErrorProperties",
|
||||
"EventSessionIdle",
|
||||
"EventSessionIdleProperties",
|
||||
"EventSessionUpdated",
|
||||
"EventSessionUpdatedProperties",
|
||||
"File",
|
||||
"FileContent",
|
||||
"FileContentPatch",
|
||||
"FileContentPatchHunksItem",
|
||||
"FileNode",
|
||||
"FileNodeType",
|
||||
"FilePart",
|
||||
"FilePartInput",
|
||||
"FilePartSourceText",
|
||||
"FileSource",
|
||||
"FileStatus",
|
||||
"KeybindsConfig",
|
||||
"LayoutConfig",
|
||||
"McpLocalConfig",
|
||||
"McpLocalConfigEnvironment",
|
||||
"McpRemoteConfig",
|
||||
"McpRemoteConfigHeaders",
|
||||
"MessageAbortedError",
|
||||
"MessageAbortedErrorData",
|
||||
"MessageOutputLengthError",
|
||||
"MessageOutputLengthErrorData",
|
||||
"Model",
|
||||
"ModelCost",
|
||||
"ModelLimit",
|
||||
"ModelOptions",
|
||||
"ModelProvider",
|
||||
"OAuth",
|
||||
"PatchPart",
|
||||
"Path",
|
||||
"Permission",
|
||||
"PermissionMetadata",
|
||||
"PermissionTime",
|
||||
"Project",
|
||||
"ProjectTime",
|
||||
"Provider",
|
||||
"ProviderAuthError",
|
||||
"ProviderAuthErrorData",
|
||||
"ProviderModels",
|
||||
"Range",
|
||||
"RangeEnd",
|
||||
"RangeStart",
|
||||
"ReasoningPart",
|
||||
"ReasoningPartMetadata",
|
||||
"ReasoningPartTime",
|
||||
"Session",
|
||||
"SessionRevert",
|
||||
"SessionShare",
|
||||
"SessionTime",
|
||||
"SnapshotPart",
|
||||
"StepFinishPart",
|
||||
"StepFinishPartTokens",
|
||||
"StepFinishPartTokensCache",
|
||||
"StepStartPart",
|
||||
"Symbol",
|
||||
"SymbolLocation",
|
||||
"SymbolSource",
|
||||
"TextPart",
|
||||
"TextPartInput",
|
||||
"TextPartInputTime",
|
||||
"TextPartTime",
|
||||
"ToolListItem",
|
||||
"ToolPart",
|
||||
"ToolStateCompleted",
|
||||
"ToolStateCompletedInput",
|
||||
"ToolStateCompletedMetadata",
|
||||
"ToolStateCompletedTime",
|
||||
"ToolStateError",
|
||||
"ToolStateErrorInput",
|
||||
"ToolStateErrorMetadata",
|
||||
"ToolStateErrorTime",
|
||||
"ToolStatePending",
|
||||
"ToolStateRunning",
|
||||
"ToolStateRunningMetadata",
|
||||
"ToolStateRunningTime",
|
||||
"UnknownError",
|
||||
"UnknownErrorData",
|
||||
"UserMessage",
|
||||
"UserMessageTime",
|
||||
"WellKnownAuth",
|
||||
)
|
||||
180
packages/sdk/python/src/opencode_ai/models/agent.py
Normal file
180
packages/sdk/python/src/opencode_ai/models/agent.py
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_model import AgentModel
|
||||
from ..models.agent_options import AgentOptions
|
||||
from ..models.agent_permission import AgentPermission
|
||||
from ..models.agent_tools import AgentTools
|
||||
|
||||
|
||||
T = TypeVar("T", bound="Agent")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class Agent:
|
||||
"""
|
||||
Attributes:
|
||||
name (str):
|
||||
mode (Union[Literal['all'], Literal['primary'], Literal['subagent']]):
|
||||
built_in (bool):
|
||||
permission (AgentPermission):
|
||||
tools (AgentTools):
|
||||
options (AgentOptions):
|
||||
description (Union[Unset, str]):
|
||||
top_p (Union[Unset, float]):
|
||||
temperature (Union[Unset, float]):
|
||||
model (Union[Unset, AgentModel]):
|
||||
prompt (Union[Unset, str]):
|
||||
"""
|
||||
|
||||
name: str
|
||||
mode: Union[Literal["all"], Literal["primary"], Literal["subagent"]]
|
||||
built_in: bool
|
||||
permission: "AgentPermission"
|
||||
tools: "AgentTools"
|
||||
options: "AgentOptions"
|
||||
description: Union[Unset, str] = UNSET
|
||||
top_p: Union[Unset, float] = UNSET
|
||||
temperature: Union[Unset, float] = UNSET
|
||||
model: Union[Unset, "AgentModel"] = UNSET
|
||||
prompt: Union[Unset, str] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
name = self.name
|
||||
|
||||
mode: Union[Literal["all"], Literal["primary"], Literal["subagent"]]
|
||||
mode = self.mode
|
||||
|
||||
built_in = self.built_in
|
||||
|
||||
permission = self.permission.to_dict()
|
||||
|
||||
tools = self.tools.to_dict()
|
||||
|
||||
options = self.options.to_dict()
|
||||
|
||||
description = self.description
|
||||
|
||||
top_p = self.top_p
|
||||
|
||||
temperature = self.temperature
|
||||
|
||||
model: Union[Unset, dict[str, Any]] = UNSET
|
||||
if not isinstance(self.model, Unset):
|
||||
model = self.model.to_dict()
|
||||
|
||||
prompt = self.prompt
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"name": name,
|
||||
"mode": mode,
|
||||
"builtIn": built_in,
|
||||
"permission": permission,
|
||||
"tools": tools,
|
||||
"options": options,
|
||||
}
|
||||
)
|
||||
if description is not UNSET:
|
||||
field_dict["description"] = description
|
||||
if top_p is not UNSET:
|
||||
field_dict["topP"] = top_p
|
||||
if temperature is not UNSET:
|
||||
field_dict["temperature"] = temperature
|
||||
if model is not UNSET:
|
||||
field_dict["model"] = model
|
||||
if prompt is not UNSET:
|
||||
field_dict["prompt"] = prompt
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_model import AgentModel
|
||||
from ..models.agent_options import AgentOptions
|
||||
from ..models.agent_permission import AgentPermission
|
||||
from ..models.agent_tools import AgentTools
|
||||
|
||||
d = dict(src_dict)
|
||||
name = d.pop("name")
|
||||
|
||||
def _parse_mode(data: object) -> Union[Literal["all"], Literal["primary"], Literal["subagent"]]:
|
||||
mode_type_0 = cast(Literal["subagent"], data)
|
||||
if mode_type_0 != "subagent":
|
||||
raise ValueError(f"mode_type_0 must match const 'subagent', got '{mode_type_0}'")
|
||||
return mode_type_0
|
||||
mode_type_1 = cast(Literal["primary"], data)
|
||||
if mode_type_1 != "primary":
|
||||
raise ValueError(f"mode_type_1 must match const 'primary', got '{mode_type_1}'")
|
||||
return mode_type_1
|
||||
mode_type_2 = cast(Literal["all"], data)
|
||||
if mode_type_2 != "all":
|
||||
raise ValueError(f"mode_type_2 must match const 'all', got '{mode_type_2}'")
|
||||
return mode_type_2
|
||||
|
||||
mode = _parse_mode(d.pop("mode"))
|
||||
|
||||
built_in = d.pop("builtIn")
|
||||
|
||||
permission = AgentPermission.from_dict(d.pop("permission"))
|
||||
|
||||
tools = AgentTools.from_dict(d.pop("tools"))
|
||||
|
||||
options = AgentOptions.from_dict(d.pop("options"))
|
||||
|
||||
description = d.pop("description", UNSET)
|
||||
|
||||
top_p = d.pop("topP", UNSET)
|
||||
|
||||
temperature = d.pop("temperature", UNSET)
|
||||
|
||||
_model = d.pop("model", UNSET)
|
||||
model: Union[Unset, AgentModel]
|
||||
if isinstance(_model, Unset):
|
||||
model = UNSET
|
||||
else:
|
||||
model = AgentModel.from_dict(_model)
|
||||
|
||||
prompt = d.pop("prompt", UNSET)
|
||||
|
||||
agent = cls(
|
||||
name=name,
|
||||
mode=mode,
|
||||
built_in=built_in,
|
||||
permission=permission,
|
||||
tools=tools,
|
||||
options=options,
|
||||
description=description,
|
||||
top_p=top_p,
|
||||
temperature=temperature,
|
||||
model=model,
|
||||
prompt=prompt,
|
||||
)
|
||||
|
||||
agent.additional_properties = d
|
||||
return agent
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
173
packages/sdk/python/src/opencode_ai/models/agent_config.py
Normal file
173
packages/sdk/python/src/opencode_ai/models/agent_config.py
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_config_permission import AgentConfigPermission
|
||||
from ..models.agent_config_tools import AgentConfigTools
|
||||
|
||||
|
||||
T = TypeVar("T", bound="AgentConfig")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentConfig:
|
||||
"""
|
||||
Attributes:
|
||||
model (Union[Unset, str]):
|
||||
temperature (Union[Unset, float]):
|
||||
top_p (Union[Unset, float]):
|
||||
prompt (Union[Unset, str]):
|
||||
tools (Union[Unset, AgentConfigTools]):
|
||||
disable (Union[Unset, bool]):
|
||||
description (Union[Unset, str]): Description of when to use the agent
|
||||
mode (Union[Literal['all'], Literal['primary'], Literal['subagent'], Unset]):
|
||||
permission (Union[Unset, AgentConfigPermission]):
|
||||
"""
|
||||
|
||||
model: Union[Unset, str] = UNSET
|
||||
temperature: Union[Unset, float] = UNSET
|
||||
top_p: Union[Unset, float] = UNSET
|
||||
prompt: Union[Unset, str] = UNSET
|
||||
tools: Union[Unset, "AgentConfigTools"] = UNSET
|
||||
disable: Union[Unset, bool] = UNSET
|
||||
description: Union[Unset, str] = UNSET
|
||||
mode: Union[Literal["all"], Literal["primary"], Literal["subagent"], Unset] = UNSET
|
||||
permission: Union[Unset, "AgentConfigPermission"] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
model = self.model
|
||||
|
||||
temperature = self.temperature
|
||||
|
||||
top_p = self.top_p
|
||||
|
||||
prompt = self.prompt
|
||||
|
||||
tools: Union[Unset, dict[str, Any]] = UNSET
|
||||
if not isinstance(self.tools, Unset):
|
||||
tools = self.tools.to_dict()
|
||||
|
||||
disable = self.disable
|
||||
|
||||
description = self.description
|
||||
|
||||
mode: Union[Literal["all"], Literal["primary"], Literal["subagent"], Unset]
|
||||
if isinstance(self.mode, Unset):
|
||||
mode = UNSET
|
||||
else:
|
||||
mode = self.mode
|
||||
|
||||
permission: Union[Unset, dict[str, Any]] = UNSET
|
||||
if not isinstance(self.permission, Unset):
|
||||
permission = self.permission.to_dict()
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update({})
|
||||
if model is not UNSET:
|
||||
field_dict["model"] = model
|
||||
if temperature is not UNSET:
|
||||
field_dict["temperature"] = temperature
|
||||
if top_p is not UNSET:
|
||||
field_dict["top_p"] = top_p
|
||||
if prompt is not UNSET:
|
||||
field_dict["prompt"] = prompt
|
||||
if tools is not UNSET:
|
||||
field_dict["tools"] = tools
|
||||
if disable is not UNSET:
|
||||
field_dict["disable"] = disable
|
||||
if description is not UNSET:
|
||||
field_dict["description"] = description
|
||||
if mode is not UNSET:
|
||||
field_dict["mode"] = mode
|
||||
if permission is not UNSET:
|
||||
field_dict["permission"] = permission
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_config_permission import AgentConfigPermission
|
||||
from ..models.agent_config_tools import AgentConfigTools
|
||||
|
||||
d = dict(src_dict)
|
||||
model = d.pop("model", UNSET)
|
||||
|
||||
temperature = d.pop("temperature", UNSET)
|
||||
|
||||
top_p = d.pop("top_p", UNSET)
|
||||
|
||||
prompt = d.pop("prompt", UNSET)
|
||||
|
||||
_tools = d.pop("tools", UNSET)
|
||||
tools: Union[Unset, AgentConfigTools]
|
||||
if isinstance(_tools, Unset):
|
||||
tools = UNSET
|
||||
else:
|
||||
tools = AgentConfigTools.from_dict(_tools)
|
||||
|
||||
disable = d.pop("disable", UNSET)
|
||||
|
||||
description = d.pop("description", UNSET)
|
||||
|
||||
def _parse_mode(data: object) -> Union[Literal["all"], Literal["primary"], Literal["subagent"], Unset]:
|
||||
if isinstance(data, Unset):
|
||||
return data
|
||||
mode_type_0 = cast(Literal["subagent"], data)
|
||||
if mode_type_0 != "subagent":
|
||||
raise ValueError(f"mode_type_0 must match const 'subagent', got '{mode_type_0}'")
|
||||
return mode_type_0
|
||||
mode_type_1 = cast(Literal["primary"], data)
|
||||
if mode_type_1 != "primary":
|
||||
raise ValueError(f"mode_type_1 must match const 'primary', got '{mode_type_1}'")
|
||||
return mode_type_1
|
||||
mode_type_2 = cast(Literal["all"], data)
|
||||
if mode_type_2 != "all":
|
||||
raise ValueError(f"mode_type_2 must match const 'all', got '{mode_type_2}'")
|
||||
return mode_type_2
|
||||
|
||||
mode = _parse_mode(d.pop("mode", UNSET))
|
||||
|
||||
_permission = d.pop("permission", UNSET)
|
||||
permission: Union[Unset, AgentConfigPermission]
|
||||
if isinstance(_permission, Unset):
|
||||
permission = UNSET
|
||||
else:
|
||||
permission = AgentConfigPermission.from_dict(_permission)
|
||||
|
||||
agent_config = cls(
|
||||
model=model,
|
||||
temperature=temperature,
|
||||
top_p=top_p,
|
||||
prompt=prompt,
|
||||
tools=tools,
|
||||
disable=disable,
|
||||
description=description,
|
||||
mode=mode,
|
||||
permission=permission,
|
||||
)
|
||||
|
||||
agent_config.additional_properties = d
|
||||
return agent_config
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_config_permission_bash_type_1 import AgentConfigPermissionBashType1
|
||||
|
||||
|
||||
T = TypeVar("T", bound="AgentConfigPermission")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentConfigPermission:
|
||||
"""
|
||||
Attributes:
|
||||
edit (Union[Literal['allow'], Literal['ask'], Literal['deny'], Unset]):
|
||||
bash (Union['AgentConfigPermissionBashType1', Literal['allow'], Literal['ask'], Literal['deny'], Unset]):
|
||||
webfetch (Union[Literal['allow'], Literal['ask'], Literal['deny'], Unset]):
|
||||
"""
|
||||
|
||||
edit: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset] = UNSET
|
||||
bash: Union["AgentConfigPermissionBashType1", Literal["allow"], Literal["ask"], Literal["deny"], Unset] = UNSET
|
||||
webfetch: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
from ..models.agent_config_permission_bash_type_1 import AgentConfigPermissionBashType1
|
||||
|
||||
edit: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]
|
||||
if isinstance(self.edit, Unset):
|
||||
edit = UNSET
|
||||
else:
|
||||
edit = self.edit
|
||||
|
||||
bash: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset, dict[str, Any]]
|
||||
if isinstance(self.bash, Unset):
|
||||
bash = UNSET
|
||||
elif isinstance(self.bash, AgentConfigPermissionBashType1):
|
||||
bash = self.bash.to_dict()
|
||||
else:
|
||||
bash = self.bash
|
||||
|
||||
webfetch: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]
|
||||
if isinstance(self.webfetch, Unset):
|
||||
webfetch = UNSET
|
||||
else:
|
||||
webfetch = self.webfetch
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update({})
|
||||
if edit is not UNSET:
|
||||
field_dict["edit"] = edit
|
||||
if bash is not UNSET:
|
||||
field_dict["bash"] = bash
|
||||
if webfetch is not UNSET:
|
||||
field_dict["webfetch"] = webfetch
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_config_permission_bash_type_1 import AgentConfigPermissionBashType1
|
||||
|
||||
d = dict(src_dict)
|
||||
|
||||
def _parse_edit(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]:
|
||||
if isinstance(data, Unset):
|
||||
return data
|
||||
edit_type_0 = cast(Literal["ask"], data)
|
||||
if edit_type_0 != "ask":
|
||||
raise ValueError(f"edit_type_0 must match const 'ask', got '{edit_type_0}'")
|
||||
return edit_type_0
|
||||
edit_type_1 = cast(Literal["allow"], data)
|
||||
if edit_type_1 != "allow":
|
||||
raise ValueError(f"edit_type_1 must match const 'allow', got '{edit_type_1}'")
|
||||
return edit_type_1
|
||||
edit_type_2 = cast(Literal["deny"], data)
|
||||
if edit_type_2 != "deny":
|
||||
raise ValueError(f"edit_type_2 must match const 'deny', got '{edit_type_2}'")
|
||||
return edit_type_2
|
||||
|
||||
edit = _parse_edit(d.pop("edit", UNSET))
|
||||
|
||||
def _parse_bash(
|
||||
data: object,
|
||||
) -> Union["AgentConfigPermissionBashType1", Literal["allow"], Literal["ask"], Literal["deny"], Unset]:
|
||||
if isinstance(data, Unset):
|
||||
return data
|
||||
bash_type_0_type_0 = cast(Literal["ask"], data)
|
||||
if bash_type_0_type_0 != "ask":
|
||||
raise ValueError(f"bash_type_0_type_0 must match const 'ask', got '{bash_type_0_type_0}'")
|
||||
return bash_type_0_type_0
|
||||
bash_type_0_type_1 = cast(Literal["allow"], data)
|
||||
if bash_type_0_type_1 != "allow":
|
||||
raise ValueError(f"bash_type_0_type_1 must match const 'allow', got '{bash_type_0_type_1}'")
|
||||
return bash_type_0_type_1
|
||||
bash_type_0_type_2 = cast(Literal["deny"], data)
|
||||
if bash_type_0_type_2 != "deny":
|
||||
raise ValueError(f"bash_type_0_type_2 must match const 'deny', got '{bash_type_0_type_2}'")
|
||||
return bash_type_0_type_2
|
||||
if not isinstance(data, dict):
|
||||
raise TypeError()
|
||||
bash_type_1 = AgentConfigPermissionBashType1.from_dict(data)
|
||||
|
||||
return bash_type_1
|
||||
|
||||
bash = _parse_bash(d.pop("bash", UNSET))
|
||||
|
||||
def _parse_webfetch(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]:
|
||||
if isinstance(data, Unset):
|
||||
return data
|
||||
webfetch_type_0 = cast(Literal["ask"], data)
|
||||
if webfetch_type_0 != "ask":
|
||||
raise ValueError(f"webfetch_type_0 must match const 'ask', got '{webfetch_type_0}'")
|
||||
return webfetch_type_0
|
||||
webfetch_type_1 = cast(Literal["allow"], data)
|
||||
if webfetch_type_1 != "allow":
|
||||
raise ValueError(f"webfetch_type_1 must match const 'allow', got '{webfetch_type_1}'")
|
||||
return webfetch_type_1
|
||||
webfetch_type_2 = cast(Literal["deny"], data)
|
||||
if webfetch_type_2 != "deny":
|
||||
raise ValueError(f"webfetch_type_2 must match const 'deny', got '{webfetch_type_2}'")
|
||||
return webfetch_type_2
|
||||
|
||||
webfetch = _parse_webfetch(d.pop("webfetch", UNSET))
|
||||
|
||||
agent_config_permission = cls(
|
||||
edit=edit,
|
||||
bash=bash,
|
||||
webfetch=webfetch,
|
||||
)
|
||||
|
||||
agent_config_permission.additional_properties = d
|
||||
return agent_config_permission
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentConfigPermissionBashType1")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentConfigPermissionBashType1:
|
||||
""" """
|
||||
|
||||
additional_properties: dict[str, Union[Literal["allow"], Literal["ask"], Literal["deny"]]] = _attrs_field(
|
||||
init=False, factory=dict
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
field_dict: dict[str, Any] = {}
|
||||
for prop_name, prop in self.additional_properties.items():
|
||||
field_dict[prop_name] = prop
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
agent_config_permission_bash_type_1 = cls()
|
||||
|
||||
additional_properties = {}
|
||||
for prop_name, prop_dict in d.items():
|
||||
|
||||
def _parse_additional_property(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"]]:
|
||||
additional_property_type_0 = cast(Literal["ask"], data)
|
||||
if additional_property_type_0 != "ask":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_0 must match const 'ask', got '{additional_property_type_0}'"
|
||||
)
|
||||
return additional_property_type_0
|
||||
additional_property_type_1 = cast(Literal["allow"], data)
|
||||
if additional_property_type_1 != "allow":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_1 must match const 'allow', got '{additional_property_type_1}'"
|
||||
)
|
||||
return additional_property_type_1
|
||||
additional_property_type_2 = cast(Literal["deny"], data)
|
||||
if additional_property_type_2 != "deny":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_2 must match const 'deny', got '{additional_property_type_2}'"
|
||||
)
|
||||
return additional_property_type_2
|
||||
|
||||
additional_property = _parse_additional_property(prop_dict)
|
||||
|
||||
additional_properties[prop_name] = additional_property
|
||||
|
||||
agent_config_permission_bash_type_1.additional_properties = additional_properties
|
||||
return agent_config_permission_bash_type_1
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Union[Literal["allow"], Literal["ask"], Literal["deny"]]:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Union[Literal["allow"], Literal["ask"], Literal["deny"]]) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentConfigTools")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentConfigTools:
|
||||
""" """
|
||||
|
||||
additional_properties: dict[str, bool] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
agent_config_tools = cls()
|
||||
|
||||
agent_config_tools.additional_properties = d
|
||||
return agent_config_tools
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> bool:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: bool) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
67
packages/sdk/python/src/opencode_ai/models/agent_model.py
Normal file
67
packages/sdk/python/src/opencode_ai/models/agent_model.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentModel")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentModel:
|
||||
"""
|
||||
Attributes:
|
||||
model_id (str):
|
||||
provider_id (str):
|
||||
"""
|
||||
|
||||
model_id: str
|
||||
provider_id: str
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
model_id = self.model_id
|
||||
|
||||
provider_id = self.provider_id
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"modelID": model_id,
|
||||
"providerID": provider_id,
|
||||
}
|
||||
)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
model_id = d.pop("modelID")
|
||||
|
||||
provider_id = d.pop("providerID")
|
||||
|
||||
agent_model = cls(
|
||||
model_id=model_id,
|
||||
provider_id=provider_id,
|
||||
)
|
||||
|
||||
agent_model.additional_properties = d
|
||||
return agent_model
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
44
packages/sdk/python/src/opencode_ai/models/agent_options.py
Normal file
44
packages/sdk/python/src/opencode_ai/models/agent_options.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentOptions")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentOptions:
|
||||
""" """
|
||||
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
agent_options = cls()
|
||||
|
||||
agent_options.additional_properties = d
|
||||
return agent_options
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
117
packages/sdk/python/src/opencode_ai/models/agent_part.py
Normal file
117
packages/sdk/python/src/opencode_ai/models/agent_part.py
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_part_source import AgentPartSource
|
||||
|
||||
|
||||
T = TypeVar("T", bound="AgentPart")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPart:
|
||||
"""
|
||||
Attributes:
|
||||
id (str):
|
||||
session_id (str):
|
||||
message_id (str):
|
||||
type_ (Literal['agent']):
|
||||
name (str):
|
||||
source (Union[Unset, AgentPartSource]):
|
||||
"""
|
||||
|
||||
id: str
|
||||
session_id: str
|
||||
message_id: str
|
||||
type_: Literal["agent"]
|
||||
name: str
|
||||
source: Union[Unset, "AgentPartSource"] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
id = self.id
|
||||
|
||||
session_id = self.session_id
|
||||
|
||||
message_id = self.message_id
|
||||
|
||||
type_ = self.type_
|
||||
|
||||
name = self.name
|
||||
|
||||
source: Union[Unset, dict[str, Any]] = UNSET
|
||||
if not isinstance(self.source, Unset):
|
||||
source = self.source.to_dict()
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"id": id,
|
||||
"sessionID": session_id,
|
||||
"messageID": message_id,
|
||||
"type": type_,
|
||||
"name": name,
|
||||
}
|
||||
)
|
||||
if source is not UNSET:
|
||||
field_dict["source"] = source
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_part_source import AgentPartSource
|
||||
|
||||
d = dict(src_dict)
|
||||
id = d.pop("id")
|
||||
|
||||
session_id = d.pop("sessionID")
|
||||
|
||||
message_id = d.pop("messageID")
|
||||
|
||||
type_ = cast(Literal["agent"], d.pop("type"))
|
||||
if type_ != "agent":
|
||||
raise ValueError(f"type must match const 'agent', got '{type_}'")
|
||||
|
||||
name = d.pop("name")
|
||||
|
||||
_source = d.pop("source", UNSET)
|
||||
source: Union[Unset, AgentPartSource]
|
||||
if isinstance(_source, Unset):
|
||||
source = UNSET
|
||||
else:
|
||||
source = AgentPartSource.from_dict(_source)
|
||||
|
||||
agent_part = cls(
|
||||
id=id,
|
||||
session_id=session_id,
|
||||
message_id=message_id,
|
||||
type_=type_,
|
||||
name=name,
|
||||
source=source,
|
||||
)
|
||||
|
||||
agent_part.additional_properties = d
|
||||
return agent_part
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
102
packages/sdk/python/src/opencode_ai/models/agent_part_input.py
Normal file
102
packages/sdk/python/src/opencode_ai/models/agent_part_input.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_part_input_source import AgentPartInputSource
|
||||
|
||||
|
||||
T = TypeVar("T", bound="AgentPartInput")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPartInput:
|
||||
"""
|
||||
Attributes:
|
||||
type_ (Literal['agent']):
|
||||
name (str):
|
||||
id (Union[Unset, str]):
|
||||
source (Union[Unset, AgentPartInputSource]):
|
||||
"""
|
||||
|
||||
type_: Literal["agent"]
|
||||
name: str
|
||||
id: Union[Unset, str] = UNSET
|
||||
source: Union[Unset, "AgentPartInputSource"] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
type_ = self.type_
|
||||
|
||||
name = self.name
|
||||
|
||||
id = self.id
|
||||
|
||||
source: Union[Unset, dict[str, Any]] = UNSET
|
||||
if not isinstance(self.source, Unset):
|
||||
source = self.source.to_dict()
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"type": type_,
|
||||
"name": name,
|
||||
}
|
||||
)
|
||||
if id is not UNSET:
|
||||
field_dict["id"] = id
|
||||
if source is not UNSET:
|
||||
field_dict["source"] = source
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_part_input_source import AgentPartInputSource
|
||||
|
||||
d = dict(src_dict)
|
||||
type_ = cast(Literal["agent"], d.pop("type"))
|
||||
if type_ != "agent":
|
||||
raise ValueError(f"type must match const 'agent', got '{type_}'")
|
||||
|
||||
name = d.pop("name")
|
||||
|
||||
id = d.pop("id", UNSET)
|
||||
|
||||
_source = d.pop("source", UNSET)
|
||||
source: Union[Unset, AgentPartInputSource]
|
||||
if isinstance(_source, Unset):
|
||||
source = UNSET
|
||||
else:
|
||||
source = AgentPartInputSource.from_dict(_source)
|
||||
|
||||
agent_part_input = cls(
|
||||
type_=type_,
|
||||
name=name,
|
||||
id=id,
|
||||
source=source,
|
||||
)
|
||||
|
||||
agent_part_input.additional_properties = d
|
||||
return agent_part_input
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentPartInputSource")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPartInputSource:
|
||||
"""
|
||||
Attributes:
|
||||
value (str):
|
||||
start (int):
|
||||
end (int):
|
||||
"""
|
||||
|
||||
value: str
|
||||
start: int
|
||||
end: int
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
value = self.value
|
||||
|
||||
start = self.start
|
||||
|
||||
end = self.end
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"value": value,
|
||||
"start": start,
|
||||
"end": end,
|
||||
}
|
||||
)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
value = d.pop("value")
|
||||
|
||||
start = d.pop("start")
|
||||
|
||||
end = d.pop("end")
|
||||
|
||||
agent_part_input_source = cls(
|
||||
value=value,
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
|
||||
agent_part_input_source.additional_properties = d
|
||||
return agent_part_input_source
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentPartSource")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPartSource:
|
||||
"""
|
||||
Attributes:
|
||||
value (str):
|
||||
start (int):
|
||||
end (int):
|
||||
"""
|
||||
|
||||
value: str
|
||||
start: int
|
||||
end: int
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
value = self.value
|
||||
|
||||
start = self.start
|
||||
|
||||
end = self.end
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"value": value,
|
||||
"start": start,
|
||||
"end": end,
|
||||
}
|
||||
)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
value = d.pop("value")
|
||||
|
||||
start = d.pop("start")
|
||||
|
||||
end = d.pop("end")
|
||||
|
||||
agent_part_source = cls(
|
||||
value=value,
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
|
||||
agent_part_source.additional_properties = d
|
||||
return agent_part_source
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
120
packages/sdk/python/src/opencode_ai/models/agent_permission.py
Normal file
120
packages/sdk/python/src/opencode_ai/models/agent_permission.py
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
from ..types import UNSET, Unset
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..models.agent_permission_bash import AgentPermissionBash
|
||||
|
||||
|
||||
T = TypeVar("T", bound="AgentPermission")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPermission:
|
||||
"""
|
||||
Attributes:
|
||||
edit (Union[Literal['allow'], Literal['ask'], Literal['deny']]):
|
||||
bash (AgentPermissionBash):
|
||||
webfetch (Union[Literal['allow'], Literal['ask'], Literal['deny'], Unset]):
|
||||
"""
|
||||
|
||||
edit: Union[Literal["allow"], Literal["ask"], Literal["deny"]]
|
||||
bash: "AgentPermissionBash"
|
||||
webfetch: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset] = UNSET
|
||||
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
edit: Union[Literal["allow"], Literal["ask"], Literal["deny"]]
|
||||
edit = self.edit
|
||||
|
||||
bash = self.bash.to_dict()
|
||||
|
||||
webfetch: Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]
|
||||
if isinstance(self.webfetch, Unset):
|
||||
webfetch = UNSET
|
||||
else:
|
||||
webfetch = self.webfetch
|
||||
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
field_dict.update(
|
||||
{
|
||||
"edit": edit,
|
||||
"bash": bash,
|
||||
}
|
||||
)
|
||||
if webfetch is not UNSET:
|
||||
field_dict["webfetch"] = webfetch
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
from ..models.agent_permission_bash import AgentPermissionBash
|
||||
|
||||
d = dict(src_dict)
|
||||
|
||||
def _parse_edit(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"]]:
|
||||
edit_type_0 = cast(Literal["ask"], data)
|
||||
if edit_type_0 != "ask":
|
||||
raise ValueError(f"edit_type_0 must match const 'ask', got '{edit_type_0}'")
|
||||
return edit_type_0
|
||||
edit_type_1 = cast(Literal["allow"], data)
|
||||
if edit_type_1 != "allow":
|
||||
raise ValueError(f"edit_type_1 must match const 'allow', got '{edit_type_1}'")
|
||||
return edit_type_1
|
||||
edit_type_2 = cast(Literal["deny"], data)
|
||||
if edit_type_2 != "deny":
|
||||
raise ValueError(f"edit_type_2 must match const 'deny', got '{edit_type_2}'")
|
||||
return edit_type_2
|
||||
|
||||
edit = _parse_edit(d.pop("edit"))
|
||||
|
||||
bash = AgentPermissionBash.from_dict(d.pop("bash"))
|
||||
|
||||
def _parse_webfetch(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"], Unset]:
|
||||
if isinstance(data, Unset):
|
||||
return data
|
||||
webfetch_type_0 = cast(Literal["ask"], data)
|
||||
if webfetch_type_0 != "ask":
|
||||
raise ValueError(f"webfetch_type_0 must match const 'ask', got '{webfetch_type_0}'")
|
||||
return webfetch_type_0
|
||||
webfetch_type_1 = cast(Literal["allow"], data)
|
||||
if webfetch_type_1 != "allow":
|
||||
raise ValueError(f"webfetch_type_1 must match const 'allow', got '{webfetch_type_1}'")
|
||||
return webfetch_type_1
|
||||
webfetch_type_2 = cast(Literal["deny"], data)
|
||||
if webfetch_type_2 != "deny":
|
||||
raise ValueError(f"webfetch_type_2 must match const 'deny', got '{webfetch_type_2}'")
|
||||
return webfetch_type_2
|
||||
|
||||
webfetch = _parse_webfetch(d.pop("webfetch", UNSET))
|
||||
|
||||
agent_permission = cls(
|
||||
edit=edit,
|
||||
bash=bash,
|
||||
webfetch=webfetch,
|
||||
)
|
||||
|
||||
agent_permission.additional_properties = d
|
||||
return agent_permission
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Any) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, Literal, TypeVar, Union, cast
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentPermissionBash")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentPermissionBash:
|
||||
""" """
|
||||
|
||||
additional_properties: dict[str, Union[Literal["allow"], Literal["ask"], Literal["deny"]]] = _attrs_field(
|
||||
init=False, factory=dict
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
field_dict: dict[str, Any] = {}
|
||||
for prop_name, prop in self.additional_properties.items():
|
||||
field_dict[prop_name] = prop
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
agent_permission_bash = cls()
|
||||
|
||||
additional_properties = {}
|
||||
for prop_name, prop_dict in d.items():
|
||||
|
||||
def _parse_additional_property(data: object) -> Union[Literal["allow"], Literal["ask"], Literal["deny"]]:
|
||||
additional_property_type_0 = cast(Literal["ask"], data)
|
||||
if additional_property_type_0 != "ask":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_0 must match const 'ask', got '{additional_property_type_0}'"
|
||||
)
|
||||
return additional_property_type_0
|
||||
additional_property_type_1 = cast(Literal["allow"], data)
|
||||
if additional_property_type_1 != "allow":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_1 must match const 'allow', got '{additional_property_type_1}'"
|
||||
)
|
||||
return additional_property_type_1
|
||||
additional_property_type_2 = cast(Literal["deny"], data)
|
||||
if additional_property_type_2 != "deny":
|
||||
raise ValueError(
|
||||
f"AdditionalProperty_type_2 must match const 'deny', got '{additional_property_type_2}'"
|
||||
)
|
||||
return additional_property_type_2
|
||||
|
||||
additional_property = _parse_additional_property(prop_dict)
|
||||
|
||||
additional_properties[prop_name] = additional_property
|
||||
|
||||
agent_permission_bash.additional_properties = additional_properties
|
||||
return agent_permission_bash
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> Union[Literal["allow"], Literal["ask"], Literal["deny"]]:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: Union[Literal["allow"], Literal["ask"], Literal["deny"]]) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
44
packages/sdk/python/src/opencode_ai/models/agent_tools.py
Normal file
44
packages/sdk/python/src/opencode_ai/models/agent_tools.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from attrs import define as _attrs_define
|
||||
from attrs import field as _attrs_field
|
||||
|
||||
T = TypeVar("T", bound="AgentTools")
|
||||
|
||||
|
||||
@_attrs_define
|
||||
class AgentTools:
|
||||
""" """
|
||||
|
||||
additional_properties: dict[str, bool] = _attrs_field(init=False, factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
field_dict: dict[str, Any] = {}
|
||||
field_dict.update(self.additional_properties)
|
||||
|
||||
return field_dict
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
||||
d = dict(src_dict)
|
||||
agent_tools = cls()
|
||||
|
||||
agent_tools.additional_properties = d
|
||||
return agent_tools
|
||||
|
||||
@property
|
||||
def additional_keys(self) -> list[str]:
|
||||
return list(self.additional_properties.keys())
|
||||
|
||||
def __getitem__(self, key: str) -> bool:
|
||||
return self.additional_properties[key]
|
||||
|
||||
def __setitem__(self, key: str, value: bool) -> None:
|
||||
self.additional_properties[key] = value
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
del self.additional_properties[key]
|
||||
|
||||
def __contains__(self, key: str) -> bool:
|
||||
return key in self.additional_properties
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue