Compare commits

...

92 Commits

Author SHA1 Message Date
Dax Raad 4f164c53d2 temporary fix for max output token 2025-08-07 22:54:59 -04:00
Dax Raad 02ef96f89b docs: fix 2025-08-07 21:49:18 -04:00
Dax Raad 8750744068 renable todo tool 2025-08-07 21:47:37 -04:00
Dax Raad 3e74107e36 looser todo tool schema 2025-08-07 21:47:37 -04:00
Jay V 160f839b25 docs: update cli 2025-08-07 19:24:08 -04:00
Jay V bf5b109c1f docs: edit agent doc 2025-08-07 18:51:54 -04:00
Dax Raad 60254d8ac0 docs: remove modes from sidebar navigation
🤖 Generated with [opencode](https://opencode.ai)

Co-Authored-By: opencode <noreply@opencode.ai>
2025-08-07 16:35:35 -04:00
Dax c34aec060f Merge agent and mode into one (#1689)
The concept of mode has been deprecated, there is now only the agent field in the config.

An agent can be cycled through as your primary agent with <tab> or you can spawn a subagent by @ mentioning it. if you include a description of when to use it, the primary agent will try to automatically use it

Full docs here: https://opencode.ai/docs/agents/
2025-08-07 16:32:12 -04:00
Jay V 12f1ad521f docs: slash commands 2025-08-07 16:16:16 -04:00
Timo Clasen 723a37ea9a fix: get session api (#1684) 2025-08-07 15:28:18 -04:00
Aiden Cline c6a46615c0 fix: modal pastes (#1677) 2025-08-07 13:23:58 -05:00
GitHub Action da29380093 ignore: update download stats 2025-08-07 2025-08-07 12:04:29 +00:00
Aiden Cline 7950ae1462 fix: text selection bug (#1664) 2025-08-07 05:32:34 -05:00
opencode 15e830410f release: v0.3.133 2025-08-07 00:30:05 +00:00
Dax Raad 1a561bb512 add api to get session 2025-08-06 20:24:36 -04:00
Jay V fecae609d9 docs: config doc edits 2025-08-06 16:10:17 -04:00
Jay V e01a540b08 docs: typos 2025-08-06 15:45:16 -04:00
Timo Clasen 54457e48bb fix(docs): small_model is not used for summarization (#1360) 2025-08-06 14:03:14 -05:00
Aiden Cline b179d08484 fix: interface conversion panic (#1655) 2025-08-06 14:02:33 -05:00
Jay V d9edd6818f docs: add undo to tutorial 2025-08-06 13:51:47 -04:00
Dax Raad 4217286b72 ignore: remove demo plugin 2025-08-06 11:36:53 -04:00
Dax Raad 28a4517ec6 add snapshot field in config to disable snapshots 2025-08-06 11:35:37 -04:00
Aiden Cline b00b2ded4f docs: update readme (#1654) 2025-08-06 09:35:02 -05:00
Aiden Cline 7b6d5b1429 chore: update marked-shiki, remove patch (#1653) 2025-08-06 08:47:53 -05:00
GitHub Action 7210db19e9 ignore: update download stats 2025-08-06 2025-08-06 12:04:53 +00:00
Yihui Khuu 90d2b26426 fix: run command should use specified model from cli args if provided (#1648) 2025-08-06 05:39:44 -05:00
Aiden Cline 6beba2c04f docs: document permissions (#1638) 2025-08-06 05:18:08 -05:00
Aiden Cline b8a0ecca98 fix: highlight after text wrap (#1640) 2025-08-06 05:17:35 -05:00
Aiden Cline ad10d3a126 fix: handle undefined agent in task tool (#1642) 2025-08-06 05:16:43 -05:00
Aiden Cline a48274f82b permissions disallow support (#1627) 2025-08-05 19:14:28 -05:00
adamdotdevin 6b25b7e95e feat: better assistant message visual 2025-08-05 19:05:44 -05:00
Jay V 030a3a7446 docs: identity 2025-08-05 19:36:10 -04:00
Timo Clasen 1a0e7f1e63 docs(plugins): fix typo (#1621) 2025-08-05 17:16:47 -05:00
Aiden Cline 677fb6032b fix: markdown table renders (#1623) 2025-08-05 17:16:35 -05:00
Timo Clasen 49aa48ce58 fix: prevent title regeneration on auto compact (#1628) 2025-08-05 17:15:50 -05:00
Dax Raad 857a3cd522 hint back to llm when tool does not exist 2025-08-05 15:58:12 -04:00
Jay V 6ed774ef62 docs: edit 2025-08-05 12:55:57 -04:00
adamdotdevin 5e825a4b6a chore: cleanup old sdk 2025-08-05 11:46:12 -05:00
Dax Raad 3db8e7c2b6 ci: send stats to posthog 2025-08-05 12:01:48 -04:00
GitHub Action b459055757 ignore: update download stats 2025-08-05 2025-08-05 12:04:48 +00:00
Yihui Khuu 2b195e82ee fix: allow disabling the default general agent (#1616) 2025-08-05 05:20:00 -05:00
Omar Shaarawi 58e889796c validate file part bounds to prevent panic (#1612) 2025-08-05 05:18:50 -05:00
Aiden Cline 51498c8de4 docs: make formatter docs a bit more clear (#1613) 2025-08-05 05:17:56 -05:00
Aiden Cline 7a495faa49 fix: server.root is not a function (#1614) 2025-08-05 05:17:32 -05:00
Timo Clasen 4957fca718 fix(plugins): improve session idle event (#1615) 2025-08-05 05:16:43 -05:00
opencode 8168626cd3 release: v0.3.130 2025-08-05 03:25:28 +00:00
Dax Raad b824809605 re-export shell $ for plugin 2025-08-04 23:20:04 -04:00
opencode 5536b14347 release: v0.3.129 2025-08-05 01:18:50 +00:00
Dax Raad 01efe236ef fix @opencode-ai/plugin exports 2025-08-04 21:12:18 -04:00
Frank 7a1f96399d sync 2025-08-04 21:09:44 -04:00
Frank 40036abb9d wip: gateway 2025-08-04 21:08:29 -04:00
Jay V 2970ba6416 docs: lock 2025-08-04 19:53:50 -04:00
Jay V 81412b6197 docs: edit new docs 2025-08-04 19:52:03 -04:00
Mahamed-Belkheir 5bf7691ea6 fix: default value for models with no cost object (#1601) 2025-08-04 16:45:35 -05:00
Min Chun Fu b1055a74d3 added vesper theme (#1602) 2025-08-04 16:45:00 -05:00
Aiden Cline ffcb27fa9a docs: make plugins page exposed (#1603) 2025-08-04 16:44:28 -05:00
opencode 38819e89b8 release: v0.3.128 2025-08-04 16:20:39 +00:00
Dax Raad 0a42068fbb hack to return tool call errors back to model 2025-08-04 12:15:24 -04:00
opencode b05decc572 release: v0.3.127 2025-08-04 16:06:13 +00:00
GitHub Action c2f487906a ignore: update download stats 2025-08-04 2025-08-04 12:04:34 +00:00
Aiden Cline ae78ec7a0c fix double help printing (#1580) 2025-08-04 05:03:27 -05:00
Frank e8c03f13dd fix docs 2025-08-04 00:23:02 -04:00
Dax Raad f85d30c484 wip: plugins 2025-08-03 21:43:58 -04:00
Dax Raad 1bac46612c wip: plugin load from package 2025-08-03 21:19:03 -04:00
Dax Raad 9ab3462821 Add workflow_dispatch trigger to typecheck workflow 2025-08-03 17:16:20 -04:00
Aiden Cline 3b36822696 fix: patch marked-shiki (#1569) 2025-08-03 16:13:35 -05:00
Dax Raad 5b731479d5 Add typecheck workflow 2025-08-03 17:12:23 -04:00
Dax Raad a50bef6913 ignore: cleanup 2025-08-03 17:09:30 -04:00
Yordis Prieto ed397c5057 chore: add ts-expected-error (#1575) 2025-08-03 17:09:19 -04:00
Yordis Prieto c9187a9f3a chore: remove unnecessary TypeScript error suppression (#1571) 2025-08-03 15:50:08 -04:00
opencode 2c67b26b5d release: v0.3.126 2025-08-03 19:45:14 +00:00
Dax Raad 170b94a99e ci: ignore 2025-08-03 15:39:34 -04:00
Dax Raad cd58f10e3c ci: ignore 2025-08-03 15:38:39 -04:00
Dax Raad ea85fdf3cd fix bash tool not showing stderr 2025-08-03 15:34:52 -04:00
Aiden Cline edda26ab33 tweak: filter out duplicate instructions (#1567) 2025-08-03 15:10:21 -04:00
Dax Raad ea4e1913c0 increase models.dev polling interval to hourly 2025-08-03 14:58:35 -04:00
Aiden Cline 5eebc8ab51 docs: fix mixed up documentation (#1564) 2025-08-03 13:01:09 -05:00
Dax Raad 21c52fd5cb fix bash tool getting stuck on interactive commands 2025-08-03 13:52:50 -04:00
opencode 5e8634afaf release: v0.3.123 2025-08-03 17:13:33 +00:00
Dax Raad d4bac5cdbd ci: ignore 2025-08-03 13:12:35 -04:00
opencode 263b266476 release: v0.3.122 2025-08-03 16:19:09 +00:00
Dax Raad 06830327e7 more efficient snapshots in parallel toolcalls 2025-08-03 12:12:28 -04:00
Giuseppe Rota 4b204fee58 fix(docs): move disabled providers paragraph to its proper section (#1547) 2025-08-03 11:28:57 -04:00
Dax Raad 99d3a0bb24 more fixes for shell 128 error 2025-08-03 11:25:58 -04:00
opencode 0930f6ac55 release: v0.3.120 2025-08-03 14:59:03 +00:00
Dax Raad 24515162fa ci: ignore 2025-08-03 10:52:35 -04:00
Dax Raad 53aa899e45 ci: ignore 2025-08-03 10:42:52 -04:00
Dax Raad 7e763e1c06 fix shell error 128 2025-08-03 10:30:23 -04:00
GitHub Action b0f2cc0c22 ignore: update download stats 2025-08-03 2025-08-03 12:04:04 +00:00
Aiden Cline f90aa62784 fix: expand tilde for file: references (#1553) 2025-08-03 06:15:06 -05:00
Dax Raad 852191f6cb ci: ignore 2025-08-03 03:54:17 -04:00
Dax Raad c5e9dc081c ci: bun cache 2025-08-03 03:53:31 -04:00
185 changed files with 4251 additions and 15155 deletions
+12 -1
View File
@@ -39,6 +39,15 @@ jobs:
with:
bun-version: 1.2.19
- name: Cache ~/.bun
id: cache-bun
uses: actions/cache@v3
with:
path: ~/.bun
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install makepkg
run: |
sudo apt-get update
@@ -53,9 +62,11 @@ jobs:
git config --global user.email "opencode@sst.dev"
git config --global user.name "opencode"
- name: Install dependencies
run: bun install
- name: Publish
run: |
bun install
OPENCODE_VERSION=${{ inputs.version }} ./script/publish.ts
env:
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
+2
View File
@@ -30,3 +30,5 @@ jobs:
git add STATS.md
git diff --staged --quiet || git commit -m "ignore: update download stats $(date -I)"
git push
env:
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
+24
View File
@@ -0,0 +1,24 @@
name: Typecheck
on:
pull_request:
branches: [dev]
workflow_dispatch:
jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.19
- name: Install dependencies
run: bun install
- name: Run typecheck
run: bun typecheck
+1 -1
View File
@@ -5,4 +5,4 @@ node_modules
.idea
.vscode
openapi.json
scratch
playground
+12
View File
@@ -0,0 +1,12 @@
---
description: You MUST use this agent when writing documentation
---
You are an expert technical documentation writer
You are not verbose
Every chunk of text should be followed by an example or something besides text
to look at.
Chunks of text should not be more than 2 sentences long.
@@ -1,44 +0,0 @@
---
description: >-
Use this agent when you need to create or improve documentation that requires
concrete examples to illustrate every concept. Examples include:
<example>Context: User has written a new API endpoint and needs documentation.
user: 'I just created a POST /users endpoint that accepts name and email
fields. Can you document this?' assistant: 'I'll use the
example-driven-docs-writer agent to create documentation with practical
examples for your API endpoint.' <commentary>Since the user needs
documentation with examples, use the example-driven-docs-writer agent to
create comprehensive docs with code samples.</commentary></example>
<example>Context: User has a complex configuration file that needs
documentation. user: 'This config file has multiple sections and I need docs
that show how each option works' assistant: 'Let me use the
example-driven-docs-writer agent to create documentation that breaks down each
configuration option with practical examples.' <commentary>The user needs
documentation that demonstrates configuration options, perfect for the
example-driven-docs-writer agent.</commentary></example>
---
You are an expert technical documentation writer who specializes in creating clear, example-rich documentation that never leaves readers guessing. Your core principle is that every concept must be immediately illustrated with concrete examples, code samples, or practical demonstrations.
Your documentation approach:
- Never write more than one sentence in any section without providing an example, code snippet, diagram, or practical illustration
- Break up longer explanations with multiple examples showing different scenarios or use cases
- Use concrete, realistic examples rather than abstract or placeholder content
- Include both basic and advanced examples when covering complex topics
- Show expected inputs, outputs, and results for all examples
- Use code blocks, bullet points, tables, or other formatting to visually separate examples from explanatory text
Structural requirements:
- Start each section with a brief one-sentence explanation followed immediately by an example
- For multi-step processes, provide an example after each step
- Include error examples and edge cases alongside success scenarios
- Use consistent formatting and naming conventions throughout examples
- Ensure examples are copy-pasteable and functional when applicable
Quality standards:
- Verify that no paragraph exceeds one sentence without an accompanying example
- Test that examples are accurate and would work in real scenarios
- Ensure examples progress logically from simple to complex
- Include context for when and why to use different approaches shown in examples
- Provide troubleshooting examples for common issues
When you receive a documentation request, immediately identify what needs examples and plan to illustrate every single concept, feature, or instruction with concrete demonstrations. Ask for clarification if you need more context to create realistic, useful examples.
+11 -12
View File
@@ -1,13 +1,12 @@
## Style
## IMPORTANT
- prefer single word variable/function names
- avoid try catch where possible - prefer to let exceptions bubble up
- avoid else statements where possible
- do not make useless helper functions - inline functionality unless the
function is reusable or composable
- prefer Bun apis
## Workflow
- you can regenerate the golang sdk by calling ./scripts/stainless.ts
- we use bun for everything
- Try to keep things in one function unless composable or reusable
- DO NOT do unnecessary destructuring of variables
- DO NOT use `else` statements unless necessary
- DO NOT use `try`/`catch` if it can be avoided
- AVOID `try`/`catch` where possible
- AVOID `else` statements
- AVOID using `any` type
- AVOID `let` statements
- PREFER single word variable names where possible
- Use as many bun apis as possible like Bun.file()
+1 -1
View File
@@ -83,7 +83,7 @@ And run.
```bash
$ bun install
$ bun run packages/opencode/src/index.ts
$ bun dev
```
#### Development Notes
+5
View File
@@ -36,3 +36,8 @@
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
+384 -13
View File
@@ -10,22 +10,27 @@
},
"packages/function": {
"name": "@opencode/function",
"version": "0.3.113",
"version": "0.3.133",
"dependencies": {
"@ai-sdk/anthropic": "2.0.0",
"@ai-sdk/openai": "2.0.2",
"@ai-sdk/openai-compatible": "1.0.1",
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "22.0.0",
"ai": "catalog:",
"hono": "catalog:",
"jose": "6.0.11",
},
"devDependencies": {
"@cloudflare/workers-types": "4.20250522.0",
"@types/node": "catalog:",
"openai": "5.11.0",
"typescript": "catalog:",
},
},
"packages/opencode": {
"name": "opencode",
"version": "0.3.113",
"version": "0.3.133",
"bin": {
"opencode": "./bin/opencode",
},
@@ -40,6 +45,13 @@
"@openauthjs/openauth": "0.4.3",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/sdk": "workspace:*",
"@opentelemetry/auto-instrumentations-node": "0.62.0",
"@opentelemetry/exporter-jaeger": "2.0.1",
"@opentelemetry/exporter-otlp-http": "0.26.0",
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
"@opentelemetry/instrumentation-fetch": "0.203.0",
"@opentelemetry/sdk-node": "0.203.0",
"@opentelemetry/sdk-trace-node": "2.0.1",
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
@@ -78,17 +90,19 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
"version": "0.3.113",
"version": "0.3.133",
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
},
"devDependencies": {
"@hey-api/openapi-ts": "0.80.1",
"@opencode-ai/sdk": "workspace:*",
"@tsconfig/node22": "catalog:",
"typescript": "catalog:",
},
},
"packages/sdk/js": {
"name": "@opencode-ai/sdk",
"version": "0.3.113",
"version": "0.3.133",
"devDependencies": {
"@hey-api/openapi-ts": "0.80.1",
"@tsconfig/node22": "catalog:",
@@ -97,7 +111,7 @@
},
"packages/web": {
"name": "@opencode/web",
"version": "0.3.113",
"version": "0.3.133",
"dependencies": {
"@astrojs/cloudflare": "^12.5.4",
"@astrojs/markdown-remark": "6.3.1",
@@ -113,7 +127,7 @@
"lang-map": "0.4.0",
"luxon": "3.6.1",
"marked": "15.0.12",
"marked-shiki": "1.2.0",
"marked-shiki": "1.2.1",
"rehype-autolink-headings": "7.1.0",
"remeda": "2.26.0",
"sharp": "0.32.5",
@@ -131,6 +145,7 @@
"trustedDependencies": [
"sharp",
"esbuild",
"protobufjs",
],
"catalog": {
"@tsconfig/node22": "22.0.2",
@@ -154,13 +169,17 @@
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@2.2.10", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-icLGO7Q0NinnHIPgT+y1QjHVwH4HwV+brWbvM+FfCG2Afpa89PyKa3Ret91kGjZpBgM/xnj1B7K5eM+rRlsXQA=="],
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.2.12", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ=="],
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-uyyaO4KhxoIKZztREqLPh+6/K3ZJx/rp72JKoUEL9/kC+vfQTThUfPnY/bUryUpcnawx8IY/tSoYNOi/8PCv7w=="],
"@ai-sdk/gateway": ["@ai-sdk/gateway@1.0.0-beta.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.2", "@ai-sdk/provider-utils": "3.0.0-beta.10" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-felWPMuECZRGx8xnmvH5dW3jywKTkGnw/tXN8szphGzEDr/BfxywuXijfPBG2WBUS6frPXsvSLDRdCm5W38PXA=="],
"@ai-sdk/provider": ["@ai-sdk/provider@2.0.0-beta.2", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-vqhtZA7R24q1XnmfmIb1fZSmHMIaJH1BVQ+0kFnNJgqWsc+V8i+yfetZ37gUc4fXATFmBuS/6O7+RPoHsZ2Fqg=="],
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.2", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-D4zYz2uR90aooKQvX1XnS00Z7PkbrcY+snUvPfm5bCabTG7bzLrVtD56nJ5bSaZG8lmuOMfXpyiEEArYLyWPpw=="],
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0-beta.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.2", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-e6WSsgM01au04/1L/v5daXHn00eKjPBQXl3jq3BfvQbQ1jo8Rls2pvrdkyVc25jBW4TV4Zm+tw+v6NAh5NPXMA=="],
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-luHVcU+yKzwv3ekKgbP3v+elUVxb2Rt+8c6w9qi7g2NYG2/pEL21oIrnaEnc6UtTZLLZX9EFBcpq2N1FQKDIMw=="],
"@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="],
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw=="],
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
@@ -324,6 +343,10 @@
"@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.2.5", "", {}, "sha512-G09N3GfuT9qj3Ax2FDZvKqZttzM3v+cco2l8uXamhKyXLdmlaUDH5o88/C3vtTHj2oT7yRKsvxz9F+BXbWKMYA=="],
"@grpc/grpc-js": ["@grpc/grpc-js@1.13.4", "", { "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg=="],
"@grpc/proto-loader": ["@grpc/proto-loader@0.7.15", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ=="],
"@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.0.6", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0", "lodash": "^4.17.21" } }, "sha512-yktiFZoWPtEW8QKS65eqKwA5MTKp88CyiL8q72WynrBs/73SAaxlSWlA2zW/DZlywZ5hX1OYzrCC0wFdvO9c2w=="],
"@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.80.1", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-AC478kg36vmmrseLZNFonZ/cmXXmDzW5yWz4PVg1S8ebJsRtVRJ/QU+mtnXfzf9avN2P0pz/AO4WAe4jyFY2gA=="],
@@ -380,6 +403,8 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
"@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="],
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw=="],
@@ -438,6 +463,170 @@
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="],
"@opentelemetry/api-metrics": ["@opentelemetry/api-metrics@0.26.0", "", { "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-idDSUTx+LRwJiHhVHhdh45SWow5u9lKNDROKu5AMzsIVPI29utH5FfT9vor8qMM6blxWWvlT22HUNdNMWqUQfQ=="],
"@opentelemetry/auto-instrumentations-node": ["@opentelemetry/auto-instrumentations-node@0.62.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/instrumentation-amqplib": "^0.50.0", "@opentelemetry/instrumentation-aws-lambda": "^0.54.0", "@opentelemetry/instrumentation-aws-sdk": "^0.56.0", "@opentelemetry/instrumentation-bunyan": "^0.49.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.49.0", "@opentelemetry/instrumentation-connect": "^0.47.0", "@opentelemetry/instrumentation-cucumber": "^0.18.0", "@opentelemetry/instrumentation-dataloader": "^0.21.0", "@opentelemetry/instrumentation-dns": "^0.47.0", "@opentelemetry/instrumentation-express": "^0.52.0", "@opentelemetry/instrumentation-fastify": "^0.48.0", "@opentelemetry/instrumentation-fs": "^0.23.0", "@opentelemetry/instrumentation-generic-pool": "^0.47.0", "@opentelemetry/instrumentation-graphql": "^0.51.0", "@opentelemetry/instrumentation-grpc": "^0.203.0", "@opentelemetry/instrumentation-hapi": "^0.50.0", "@opentelemetry/instrumentation-http": "^0.203.0", "@opentelemetry/instrumentation-ioredis": "^0.51.0", "@opentelemetry/instrumentation-kafkajs": "^0.12.0", "@opentelemetry/instrumentation-knex": "^0.48.0", "@opentelemetry/instrumentation-koa": "^0.51.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.48.0", "@opentelemetry/instrumentation-memcached": "^0.47.0", "@opentelemetry/instrumentation-mongodb": "^0.56.0", "@opentelemetry/instrumentation-mongoose": "^0.50.0", "@opentelemetry/instrumentation-mysql": "^0.49.0", "@opentelemetry/instrumentation-mysql2": "^0.49.0", "@opentelemetry/instrumentation-nestjs-core": "^0.49.0", "@opentelemetry/instrumentation-net": "^0.47.0", "@opentelemetry/instrumentation-oracledb": "^0.29.0", "@opentelemetry/instrumentation-pg": "^0.55.0", "@opentelemetry/instrumentation-pino": "^0.50.0", "@opentelemetry/instrumentation-redis": "^0.51.0", "@opentelemetry/instrumentation-restify": "^0.49.0", "@opentelemetry/instrumentation-router": "^0.48.0", "@opentelemetry/instrumentation-runtime-node": "^0.17.0", "@opentelemetry/instrumentation-socket.io": "^0.50.0", "@opentelemetry/instrumentation-tedious": "^0.22.0", "@opentelemetry/instrumentation-undici": "^0.14.0", "@opentelemetry/instrumentation-winston": "^0.48.0", "@opentelemetry/resource-detector-alibaba-cloud": "^0.31.3", "@opentelemetry/resource-detector-aws": "^2.3.0", "@opentelemetry/resource-detector-azure": "^0.10.0", "@opentelemetry/resource-detector-container": "^0.7.3", "@opentelemetry/resource-detector-gcp": "^0.37.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-node": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.4.1", "@opentelemetry/core": "^2.0.0" } }, "sha512-h5g+VNJjiyX6u/IQpn36ZCHOENg1QW0GgBOHBcFGnHBBhmTww4R3brExdeuYbvLj3UQY09n+UHFEoMOqkhq07A=="],
"@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.0.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw=="],
"@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="],
"@opentelemetry/exporter-jaeger": ["@opentelemetry/exporter-jaeger@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0", "jaeger-client": "^3.15.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-FeHtOp2XMhYxzYhC8sXhsc3gMeoDzjI+CGuPX+vRSyUdHZHDKTMoY9jRfk8ObmZsZDTWmd63Yqcf4X472YtHeA=="],
"@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw=="],
"@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw=="],
"@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw=="],
"@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ=="],
"@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ=="],
"@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg=="],
"@opentelemetry/exporter-otlp-http": ["@opentelemetry/exporter-otlp-http@0.26.0", "", { "dependencies": { "@opentelemetry/api-metrics": "0.26.0", "@opentelemetry/core": "1.0.0", "@opentelemetry/resources": "1.0.0", "@opentelemetry/sdk-metrics-base": "0.26.0", "@opentelemetry/sdk-trace-base": "1.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-V3FcUEIVDZ66b3/6vjSBjwwozf/XV5eUXuELNzN8PAvGZH4mw36vaWlaxnGEV8HaZb2hbu2KbRpcOzqxx3tFDA=="],
"@opentelemetry/exporter-prometheus": ["@opentelemetry/exporter-prometheus@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg=="],
"@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA=="],
"@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw=="],
"@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ=="],
"@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw=="],
"@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ=="],
"@opentelemetry/instrumentation-amqplib": ["@opentelemetry/instrumentation-amqplib@0.50.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-kwNs/itehHG/qaQBcVrLNcvXVPW0I4FCOVtw3LHMLdYIqD7GJ6Yv2nX+a4YHjzbzIeRYj8iyMp0Bl7tlkidq5w=="],
"@opentelemetry/instrumentation-aws-lambda": ["@opentelemetry/instrumentation-aws-lambda@0.54.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/aws-lambda": "8.10.150" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-uiYI+kcMUJ/H9cxAwB8c9CaG8behLRgcYSOEA8M/tMQ54Y1ZmzAuEE3QKOi21/s30x5Q+by9g7BwiVfDtqzeMA=="],
"@opentelemetry/instrumentation-aws-sdk": ["@opentelemetry/instrumentation-aws-sdk@0.56.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/propagation-utils": "^0.31.3", "@opentelemetry/semantic-conventions": "^1.34.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Jl2B/FYEb6tBCk9G31CMomKPikGU2g+CEhrGddDI0o1YeNpg3kAO9dExF+w489/IJUGZX6/wudyNvV7z4k9NjQ=="],
"@opentelemetry/instrumentation-bunyan": ["@opentelemetry/instrumentation-bunyan@0.49.0", "", { "dependencies": { "@opentelemetry/api-logs": "^0.203.0", "@opentelemetry/instrumentation": "^0.203.0", "@types/bunyan": "1.8.11" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ky5Am1y6s3Ex/3RygHxB/ZXNG07zPfg9Z6Ora+vfeKcr/+I6CJbWXWhSBJor3gFgKN3RvC11UWVURnmDpBS6Pg=="],
"@opentelemetry/instrumentation-cassandra-driver": ["@opentelemetry/instrumentation-cassandra-driver@0.49.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-BNIvqldmLkeikfI5w5Rlm9vG5NnQexfPoxOgEMzfDVOEF+vS6351I6DzWLLgWWR9CNF/jQJJi/lr6am2DLp0Rw=="],
"@opentelemetry/instrumentation-connect": ["@opentelemetry/instrumentation-connect@0.47.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.38" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pjenvjR6+PMRb6/4X85L4OtkQCootgb/Jzh/l/Utu3SJHBid1F+gk9sTGU2FWuhhEfV6P7MZ7BmCdHXQjgJ42g=="],
"@opentelemetry/instrumentation-cucumber": ["@opentelemetry/instrumentation-cucumber@0.18.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-i+cUbLHvRShuevtM0NwjQR9wnABhmYw8+dbgD57LNBde7xkuSDot0CTzX+pYn32djtQ1bPYZiLf+uwS0JsMUrw=="],
"@opentelemetry/instrumentation-dataloader": ["@opentelemetry/instrumentation-dataloader@0.21.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Xu4CZ1bfhdkV3G6iVHFgKTgHx8GbKSqrTU01kcIJRGHpowVnyOPEv1CW5ow+9GU2X4Eki8zoNuVUenFc3RluxQ=="],
"@opentelemetry/instrumentation-dns": ["@opentelemetry/instrumentation-dns@0.47.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-775fOnewWkTF4iXMGKgwvOGqEmPrU1PZpXjjqvTrEErYBJe7Fz1WlEeUStHepyKOdld7Ghv7TOF/kE3QDctvrg=="],
"@opentelemetry/instrumentation-express": ["@opentelemetry/instrumentation-express@0.52.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-W7pizN0Wh1/cbNhhTf7C62NpyYw7VfCFTYg0DYieSTrtPBT1vmoSZei19wfKLnrMsz3sHayCg0HxCVL2c+cz5w=="],
"@opentelemetry/instrumentation-fastify": ["@opentelemetry/instrumentation-fastify@0.48.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-3zQlE/DoVfVH6/ycuTv7vtR/xib6WOa0aLFfslYcvE62z0htRu/ot8PV/zmMZfnzpTQj8S/4ULv36R6UIbpJIg=="],
"@opentelemetry/instrumentation-fetch": ["@opentelemetry/instrumentation-fetch@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/sdk-trace-web": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Z+mls3rOP2BaVykDZLLZPvchjj9l2oj3dYG1GTnrc27Y8o3biE+5M1b0izblycbbQHXjMPHQCpmjHbLMQuWtBg=="],
"@opentelemetry/instrumentation-fs": ["@opentelemetry/instrumentation-fs@0.23.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Puan+QopWHA/KNYvDfOZN6M/JtF6buXEyD934vrb8WhsX1/FuM7OtoMlQyIqAadnE8FqqDL4KDPiEfCQH6pQcQ=="],
"@opentelemetry/instrumentation-generic-pool": ["@opentelemetry/instrumentation-generic-pool@0.47.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-UfHqf3zYK+CwDwEtTjaD12uUqGGTswZ7ofLBEdQ4sEJp9GHSSJMQ2hT3pgBxyKADzUdoxQAv/7NqvL42ZI+Qbw=="],
"@opentelemetry/instrumentation-graphql": ["@opentelemetry/instrumentation-graphql@0.51.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-LchkOu9X5DrXAnPI1+Z06h/EH/zC7D6sA86hhPrk3evLlsJTz0grPrkL/yUJM9Ty0CL/y2HSvmWQCjbJEz/ADg=="],
"@opentelemetry/instrumentation-grpc": ["@opentelemetry/instrumentation-grpc@0.203.0", "", { "dependencies": { "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Qmjx2iwccHYRLoE4RFS46CvQE9JG9Pfeae4EPaNZjvIuJxb/pZa2R9VWzRlTehqQWpAvto/dGhtkw8Tv+o0LTg=="],
"@opentelemetry/instrumentation-hapi": ["@opentelemetry/instrumentation-hapi@0.50.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-5xGusXOFQXKacrZmDbpHQzqYD1gIkrMWuwvlrEPkYOsjUqGUjl1HbxCsn5Y9bUXOCgP1Lj6A4PcKt1UiJ2MujA=="],
"@opentelemetry/instrumentation-http": ["@opentelemetry/instrumentation-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g=="],
"@opentelemetry/instrumentation-ioredis": ["@opentelemetry/instrumentation-ioredis@0.51.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/redis-common": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9IUws0XWCb80NovS+17eONXsw1ZJbHwYYMXiwsfR9TSurkLV5UNbRSKb9URHO+K+pIJILy9wCxvyiOneMr91Ig=="],
"@opentelemetry/instrumentation-kafkajs": ["@opentelemetry/instrumentation-kafkajs@0.12.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.30.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-bIe4aSAAxytp88nzBstgr6M7ZiEpW6/D1/SuKXdxxuprf18taVvFL2H5BDNGZ7A14K27haHqzYqtCTqFXHZOYg=="],
"@opentelemetry/instrumentation-knex": ["@opentelemetry/instrumentation-knex@0.48.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.33.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-V5wuaBPv/lwGxuHjC6Na2JFRjtPgstw19jTFl1B1b6zvaX8zVDYUDaR5hL7glnQtUSCMktPttQsgK4dhXpddcA=="],
"@opentelemetry/instrumentation-koa": ["@opentelemetry/instrumentation-koa@0.51.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-XNLWeMTMG1/EkQBbgPYzCeBD0cwOrfnn8ao4hWgLv0fNCFQu1kCsJYygz2cvKuCs340RlnG4i321hX7R8gj3Rg=="],
"@opentelemetry/instrumentation-lru-memoizer": ["@opentelemetry/instrumentation-lru-memoizer@0.48.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-KUW29wfMlTPX1wFz+NNrmE7IzN7NWZDrmFWHM/VJcmFEuQGnnBuTIdsP55CnBDxKgQ/qqYFp4udQFNtjeFosPw=="],
"@opentelemetry/instrumentation-memcached": ["@opentelemetry/instrumentation-memcached@0.47.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/memcached": "^2.2.6" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-vXDs/l4hlWy1IepPG1S6aYiIZn+tZDI24kAzwKKJmR2QEJRL84PojmALAEJGazIOLl/VdcCPZdMb0U2K0VzojA=="],
"@opentelemetry/instrumentation-mongodb": ["@opentelemetry/instrumentation-mongodb@0.56.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-YG5IXUUmxX3Md2buVMvxm9NWlKADrnavI36hbJsihqqvBGsWnIfguf0rUP5Srr0pfPqhQjUP+agLMsvu0GmUpA=="],
"@opentelemetry/instrumentation-mongoose": ["@opentelemetry/instrumentation-mongoose@0.50.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Am8pk1Ct951r4qCiqkBcGmPIgGhoDiFcRtqPSLbJrUZqEPUsigjtMjoWDRLG1Ki1NHgOF7D0H7d+suWz1AAizw=="],
"@opentelemetry/instrumentation-mysql": ["@opentelemetry/instrumentation-mysql@0.49.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/mysql": "2.15.27" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-QU9IUNqNsrlfE3dJkZnFHqLjlndiU39ll/YAAEvWE40sGOCi9AtOF6rmEGzJ1IswoZ3oyePV7q2MP8SrhJfVAA=="],
"@opentelemetry/instrumentation-mysql2": ["@opentelemetry/instrumentation-mysql2@0.49.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@opentelemetry/sql-common": "^0.41.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-dCub9wc02mkJWNyHdVEZ7dvRzy295SmNJa+LrAJY2a/+tIiVBQqEAajFzKwp9zegVVnel9L+WORu34rGLQDzxA=="],
"@opentelemetry/instrumentation-nestjs-core": ["@opentelemetry/instrumentation-nestjs-core@0.49.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.30.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-1R/JFwdmZIk3T/cPOCkVvFQeKYzbbUvDxVH3ShXamUwBlGkdEu5QJitlRMyVNZaHkKZKWgYrBarGQsqcboYgaw=="],
"@opentelemetry/instrumentation-net": ["@opentelemetry/instrumentation-net@0.47.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-csoJ++Njpf7C09JH+0HNGenuNbDZBqO1rFhMRo6s0rAmJwNh9zY3M/urzptmKlqbKnf4eH0s+CKHy/+M8fbFsQ=="],
"@opentelemetry/instrumentation-oracledb": ["@opentelemetry/instrumentation-oracledb@0.29.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/oracledb": "6.5.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-2aHLiJdkyiUbooIUm7FaZf+O4jyqEl+RfFpgud1dxT87QeeYM216wi+xaMNzsb5yKtRBqbA3qeHBCyenYrOZwA=="],
"@opentelemetry/instrumentation-pg": ["@opentelemetry/instrumentation-pg@0.55.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@opentelemetry/sql-common": "^0.41.0", "@types/pg": "8.15.4", "@types/pg-pool": "2.0.6" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-yfJ5bYE7CnkW/uNsnrwouG/FR7nmg09zdk2MSs7k0ZOMkDDAE3WBGpVFFApGgNu2U+gtzLgEzOQG4I/X+60hXw=="],
"@opentelemetry/instrumentation-pino": ["@opentelemetry/instrumentation-pino@0.50.0", "", { "dependencies": { "@opentelemetry/api-logs": "^0.203.0", "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Pi0cWGp4f2gresq2xqef4IsuunLdebJ9n9tZxytDz2ci4euIfW36ILpszQmRNhwCVDCZLmUgGDKZGj4PXyPd0w=="],
"@opentelemetry/instrumentation-redis": ["@opentelemetry/instrumentation-redis@0.51.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/redis-common": "^0.38.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-uL/GtBA0u72YPPehwOvthAe+Wf8k3T+XQPBssJmTYl6fzuZjNq8zTfxVFhl9nRFjFVEe+CtiYNT0Q3AyqW1Z0A=="],
"@opentelemetry/instrumentation-restify": ["@opentelemetry/instrumentation-restify@0.49.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-tsGZZhS4mVZH7omYxw5jpsrD3LhWizqWc0PYtAnzpFUvL5ZINHE+cm57bssTQ2AK/GtZMxu9LktwCvIIf3dSmw=="],
"@opentelemetry/instrumentation-router": ["@opentelemetry/instrumentation-router@0.48.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Wixrc8CchuJojXpaS/dCQjFOMc+3OEil1H21G+WLYQb8PcKt5kzW9zDBT19nyjjQOx/D/uHPfgbrT+Dc7cfJ9w=="],
"@opentelemetry/instrumentation-runtime-node": ["@opentelemetry/instrumentation-runtime-node@0.17.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-O+xc0woqrSjue5IgpCCMvlgsuDrq6DDEfiHW3S3vRMCjXE1ZoPjaDE/K6EURorN+tjnzZQN1gOMSrscSGAbjHg=="],
"@opentelemetry/instrumentation-socket.io": ["@opentelemetry/instrumentation-socket.io@0.50.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-6JN6lnKN9ZuZtZdMQIR+no1qHzQvXSZUsNe3sSWMgqmNRyEXuDUWBIyKKeG0oHRHtR4xE4QhJyD4D5kKRPWZFA=="],
"@opentelemetry/instrumentation-tedious": ["@opentelemetry/instrumentation-tedious@0.22.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.203.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/tedious": "^4.0.14" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-XrrNSUCyEjH1ax9t+Uo6lv0S2FCCykcF7hSxBMxKf7Xn0bPRxD3KyFUZy25aQXzbbbUHhtdxj3r2h88SfEM3aA=="],
"@opentelemetry/instrumentation-undici": ["@opentelemetry/instrumentation-undici@0.14.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.7.0" } }, "sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg=="],
"@opentelemetry/instrumentation-winston": ["@opentelemetry/instrumentation-winston@0.48.0", "", { "dependencies": { "@opentelemetry/api-logs": "^0.203.0", "@opentelemetry/instrumentation": "^0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-QuKbswAaQfRULhtlYbeNC9gOAXPxOSCE4BjIzuY1oEsc84kIsHUjn3yvY9Q83s3eg3j0JycNcAMi8u0yTl5PIQ=="],
"@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ=="],
"@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ=="],
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A=="],
"@opentelemetry/propagation-utils": ["@opentelemetry/propagation-utils@0.31.3", "", { "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-ZI6LKjyo+QYYZY5SO8vfoCQ9A69r1/g+pyjvtu5RSK38npINN1evEmwqbqhbg2CdcIK3a4PN6pDAJz/yC5/gAA=="],
"@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw=="],
"@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w=="],
"@opentelemetry/redis-common": ["@opentelemetry/redis-common@0.38.0", "", {}, "sha512-4Wc0AWURII2cfXVVoZ6vDqK+s5n4K5IssdrlVrvGsx6OEOKdghKtJZqXAHWFiZv4nTDLH2/2fldjIHY8clMOjQ=="],
"@opentelemetry/resource-detector-alibaba-cloud": ["@opentelemetry/resource-detector-alibaba-cloud@0.31.3", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-I556LHcLVsBXEgnbPgQISP/JezDt5OfpgOaJNR1iVJl202r+K145OSSOxnH5YOc/KvrydBD0FOE03F7x0xnVTw=="],
"@opentelemetry/resource-detector-aws": ["@opentelemetry/resource-detector-aws@2.3.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-PkD/lyXG3B3REq1Y6imBLckljkJYXavtqGYSryAeJYvGOf5Ds3doR+BCGjmKeF6ObAtI5MtpBeUStTDtGtBsWA=="],
"@opentelemetry/resource-detector-azure": ["@opentelemetry/resource-detector-azure@0.10.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-5cNAiyPBg53Uxe/CW7hsCq8HiKNAUGH+gi65TtgpzSR9bhJG4AEbuZhbJDFwe97tn2ifAD1JTkbc/OFuaaFWbA=="],
"@opentelemetry/resource-detector-container": ["@opentelemetry/resource-detector-container@0.7.3", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-SK+xUFw6DKYbQniaGmIFsFxAZsr8RpRSRWxKi5/ZJAoqqPnjcyGI/SeUx8zzPk4XLO084zyM4pRHgir0hRTaSQ=="],
"@opentelemetry/resource-detector-gcp": ["@opentelemetry/resource-detector-gcp@0.37.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.27.0", "gcp-metadata": "^6.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-LGpJBECIMsVKhiulb4nxUw++m1oF4EiDDPmFGW2aqYaAF0oUvJNv8Z/55CAzcZ7SxvlTgUwzewXDBsuCup7iqw=="],
"@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="],
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw=="],
"@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g=="],
"@opentelemetry/sdk-metrics-base": ["@opentelemetry/sdk-metrics-base@0.26.0", "", { "dependencies": { "@opentelemetry/api-metrics": "0.26.0", "@opentelemetry/core": "1.0.0", "@opentelemetry/resources": "1.0.0", "lodash.merge": "^4.6.2" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-PbJsso7Vy/CLATAOyXbt/VP7ZQ2QYnvlq28lhOWaLPw8aqLogMBvidNGRrt7rF4/hfzLT6pMgpAAcit2C/nUMA=="],
"@opentelemetry/sdk-node": ["@opentelemetry/sdk-node@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", "@opentelemetry/exporter-logs-otlp-http": "0.203.0", "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", "@opentelemetry/exporter-prometheus": "0.203.0", "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", "@opentelemetry/exporter-trace-otlp-http": "0.203.0", "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", "@opentelemetry/exporter-zipkin": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/propagator-b3": "2.0.1", "@opentelemetry/propagator-jaeger": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/sdk-trace-node": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ=="],
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="],
"@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.0.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.0.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA=="],
"@opentelemetry/sdk-trace-web": ["@opentelemetry/sdk-trace-web@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-R4/i0rISvAujG4Zwk3s6ySyrWG+Db3SerZVM4jZ2lEzjrNylF7nRAy1hVvWe8gTbwIxX+6w6ZvZwdtl2C7UQHQ=="],
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.36.0", "", {}, "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ=="],
"@opentelemetry/sql-common": ["@opentelemetry/sql-common@0.41.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0" } }, "sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA=="],
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
"@oslojs/binary": ["@oslojs/binary@1.0.0", "", {}, "sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ=="],
@@ -466,6 +655,26 @@
"@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="],
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="],
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
"@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="],
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.2.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.46.2", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="],
@@ -548,6 +757,8 @@
"@tsconfig/node22": ["@tsconfig/node22@22.0.2", "", {}, "sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA=="],
"@types/aws-lambda": ["@types/aws-lambda@8.10.150", "", {}, "sha512-AX+AbjH/rH5ezX1fbK8onC/a+HyQHo7QGmvoxAE42n22OsciAxvZoZNEr22tbXs8WfP1nIsBjKDpgPm3HjOZbA=="],
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
@@ -558,6 +769,10 @@
"@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="],
"@types/bunyan": ["@types/bunyan@1.8.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ=="],
"@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
@@ -578,16 +793,28 @@
"@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
"@types/memcached": ["@types/memcached@2.2.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/mysql": ["@types/mysql@2.15.27", "", { "dependencies": { "@types/node": "*" } }, "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA=="],
"@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="],
"@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="],
"@types/oracledb": ["@types/oracledb@6.5.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-kK1eBS/Adeyis+3OlBDMeQQuasIDLUYXsi2T15ccNJ0iyUpQ4xDF7svFu3+bGVrI0CMBUclPciz+lsQR3JX3TQ=="],
"@types/pg": ["@types/pg@8.15.4", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg=="],
"@types/pg-pool": ["@types/pg-pool@2.0.6", "", { "dependencies": { "@types/pg": "*" } }, "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ=="],
"@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],
"@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="],
"@types/tedious": ["@types/tedious@4.0.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw=="],
"@types/turndown": ["@types/turndown@5.0.5", "", {}, "sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
@@ -604,16 +831,22 @@
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
"acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="],
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"ai": ["ai@5.0.0-beta.34", "", { "dependencies": { "@ai-sdk/gateway": "1.0.0-beta.19", "@ai-sdk/provider": "2.0.0-beta.2", "@ai-sdk/provider-utils": "3.0.0-beta.10", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-AFJ4p35AxA+1KFtnoouePLaAUpoj0IxIAoq/xgIv88qzYajTg4Sac5KaV4CDHFRLoF0L2cwhlFXt/Ss/zyBKkA=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
"ansi-color": ["ansi-color@0.2.1", "", {}, "sha512-bF6xLaZBLpOQzgYUtYEhJx090nPSZk1BQ/q2oyBK9aMMcJHzx9uXGCjI2Y+LebsN4Jwoykr0V9whbPiogdyHoQ=="],
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
@@ -676,6 +909,8 @@
"before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="],
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
@@ -694,6 +929,8 @@
"buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
"bufrw": ["bufrw@1.4.0", "", { "dependencies": { "ansi-color": "^0.2.1", "error": "^7.0.0", "hexer": "^1.5.0", "xtend": "^4.0.0" } }, "sha512-sWm8iPbqvL9+5SiYxXH73UOkyEbGQg7kyHQmReF89WJHQJw2eV4P/yZ0E+b71cczJ4pPobVhXxgQcmfSTgGHxQ=="],
"bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
@@ -732,6 +969,8 @@
"citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="],
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
"clean-git-ref": ["clean-git-ref@2.0.1", "", {}, "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw=="],
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
@@ -858,6 +1097,8 @@
"entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
"error": ["error@7.0.2", "", { "dependencies": { "string-template": "~0.2.1", "xtend": "~4.0.0" } }, "sha512-UtVv4l5MhijsYUxPJo4390gzfZvAnTHreNnDjnTZaKIiZ/SemXxAhBkYSKtWa5RtBXbLP8tMgn/n0RUa/H7jXw=="],
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
@@ -944,6 +1185,8 @@
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
"forwarded-parse": ["forwarded-parse@2.1.2", "", {}, "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw=="],
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
@@ -954,6 +1197,10 @@
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="],
"gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="],
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
@@ -972,6 +1219,8 @@
"glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="],
"google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
@@ -1030,6 +1279,8 @@
"hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
"hexer": ["hexer@1.5.0", "", { "dependencies": { "ansi-color": "^0.2.1", "minimist": "^1.1.0", "process": "^0.10.0", "xtend": "^4.0.0" }, "bin": { "hexer": "./cli.js" } }, "sha512-dyrPC8KzBzUJ19QTIo1gXNqIISRXQ0NwteW6OeQHRN4ZuZeHkdODfj0zHBdOlHbRY8GqbqK57C9oWSvQZizFsg=="],
"hono": ["hono@4.7.10", "", {}, "sha512-QkACju9MiN59CKSY5JsGZCYmPZkA6sIW6OFCUp7qDjZu6S6KHtJHhAc9Uy9mV9F8PJ1/HQ3ybZF2yjCa/73fvQ=="],
"hono-openapi": ["hono-openapi@0.4.8", "", { "dependencies": { "json-schema-walker": "^2.0.0" }, "peerDependencies": { "@hono/arktype-validator": "^2.0.0", "@hono/effect-validator": "^1.2.0", "@hono/typebox-validator": "^0.2.0 || ^0.3.0", "@hono/valibot-validator": "^0.5.1", "@hono/zod-validator": "^0.4.1", "@sinclair/typebox": "^0.34.9", "@valibot/to-json-schema": "^1.0.0-beta.3", "arktype": "^2.0.0", "effect": "^3.11.3", "hono": "^4.6.13", "openapi-types": "^12.1.3", "valibot": "^1.0.0-beta.9", "zod": "^3.23.8", "zod-openapi": "^4.0.0" }, "optionalPeers": ["@hono/arktype-validator", "@hono/effect-validator", "@hono/typebox-validator", "@hono/valibot-validator", "@hono/zod-validator", "@sinclair/typebox", "@valibot/to-json-schema", "arktype", "effect", "hono", "valibot", "zod", "zod-openapi"] }, "sha512-LYr5xdtD49M7hEAduV1PftOMzuT8ZNvkyWfh1DThkLsIr4RkvDb12UxgIiFbwrJB6FLtFXLoOZL9x4IeDk2+VA=="],
@@ -1046,6 +1297,8 @@
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
"i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="],
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
@@ -1054,6 +1307,8 @@
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"import-in-the-middle": ["import-in-the-middle@1.14.2", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw=="],
"import-meta-resolve": ["import-meta-resolve@4.1.0", "", {}, "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
@@ -1076,6 +1331,8 @@
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
@@ -1096,6 +1353,8 @@
"is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
"is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
"is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="],
@@ -1108,6 +1367,8 @@
"isomorphic-git": ["isomorphic-git@1.32.1", "", { "dependencies": { "async-lock": "^1.4.1", "clean-git-ref": "^2.0.1", "crc-32": "^1.2.0", "diff3": "0.0.3", "ignore": "^5.1.4", "minimisted": "^2.0.0", "pako": "^1.0.10", "path-browserify": "^1.0.1", "pify": "^4.0.1", "readable-stream": "^3.4.0", "sha.js": "^2.4.9", "simple-get": "^4.0.1" }, "bin": { "isogit": "cli.cjs" } }, "sha512-NZCS7qpLkCZ1M/IrujYBD31sM6pd/fMVArK4fz4I7h6m0rUW2AsYU7S7zXeABuHL6HIfW6l53b4UQ/K441CQjg=="],
"jaeger-client": ["jaeger-client@3.19.0", "", { "dependencies": { "node-int64": "^0.4.0", "opentracing": "^0.14.4", "thriftrw": "^3.5.0", "uuid": "^8.3.2", "xorshift": "^1.1.1" } }, "sha512-M0c7cKHmdyEUtjemnJyx/y9uX16XHocL46yQvyqDlPdvAcwPDbHrIbKjQdBqtiE4apQ/9dmr+ZLJYYPGnurgpw=="],
"jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
"jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="],
@@ -1122,6 +1383,8 @@
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
@@ -1144,6 +1407,12 @@
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"long": ["long@2.4.0", "", {}, "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ=="],
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
@@ -1160,7 +1429,7 @@
"marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="],
"marked-shiki": ["marked-shiki@1.2.0", "", { "peerDependencies": { "marked": ">=7.0.0", "shiki": ">=1.0.0" } }, "sha512-N924hp8veE6Mc91g5/kCNVoTU7TkeJfB2G2XEWb+k1fVA0Bck2T0rVt93d39BlOYH6ohP4Q9BFlPk+UkblhXbg=="],
"marked-shiki": ["marked-shiki@1.2.1", "", { "peerDependencies": { "marked": ">=7.0.0", "shiki": ">=1.0.0" } }, "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
@@ -1306,6 +1575,8 @@
"mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="],
"module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
@@ -1332,6 +1603,8 @@
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
"node-mock-http": ["node-mock-http@1.0.2", "", {}, "sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g=="],
"node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],
@@ -1364,6 +1637,8 @@
"open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="],
"openai": ["openai@5.11.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-+AuTc5pVjlnTuA9zvn8rA/k+1RluPIx9AD4eDcnutv6JNwHHZxIhkFy+tmMKCvmMFDQzfA/r1ujvPWB19DQkYg=="],
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
"opencode": ["opencode@workspace:packages/opencode"],
@@ -1372,6 +1647,8 @@
"openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="],
"opentracing": ["opentracing@0.14.7", "", {}, "sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q=="],
"p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="],
"p-queue": ["p-queue@8.1.0", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw=="],
@@ -1396,12 +1673,20 @@
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
"pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
"pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="],
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
@@ -1420,16 +1705,28 @@
"postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
"postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
"prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
"prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="],
"prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="],
"process": ["process@0.10.1", "", {}, "sha512-dyIett8dgGIZ/TXKUzeYExt7WA6ldDzys9vTDU/cCA9L17Ypme+KzS+NjQCjpn9xsvi/shbMC+yP/BcFMBz0NA=="],
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
"protobufjs": ["protobufjs@7.5.3", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw=="],
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
@@ -1500,6 +1797,12 @@
"remeda": ["remeda@2.26.0", "", { "dependencies": { "type-fest": "^4.41.0" } }, "sha512-lmNNwtaC6Co4m0WTTNoZ/JlpjEqAjPZO0+czC9YVRQUpkbS4x8Hmh+Mn9HPfJfiXqUQ5IXXgSXSOB2pBKAytdA=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
"require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="],
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
"restructure": ["restructure@3.0.2", "", {}, "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw=="],
"retext": ["retext@9.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "retext-latin": "^4.0.0", "retext-stringify": "^4.0.0", "unified": "^11.0.0" } }, "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA=="],
@@ -1610,6 +1913,8 @@
"streamx": ["streamx@2.22.1", "", { "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA=="],
"string-template": ["string-template@0.2.1", "", {}, "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw=="],
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
@@ -1628,6 +1933,8 @@
"supports-color": ["supports-color@10.0.0", "", {}, "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
"tar-fs": ["tar-fs@3.1.0", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w=="],
@@ -1636,6 +1943,8 @@
"text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="],
"thriftrw": ["thriftrw@3.11.4", "", { "dependencies": { "bufrw": "^1.2.1", "error": "7.0.2", "long": "^2.4.0" }, "bin": { "thrift2json": "thrift2json.js" } }, "sha512-UcuBd3eanB3T10nXWRRMwfwoaC6VMk7qe3/5YIWP2Jtw+EbHqJ0p1/K3x8ixiR5dozKSSfcg1W+0e33G1Di3XA=="],
"tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
@@ -1792,6 +2101,10 @@
"xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
"xorshift": ["xorshift@1.2.0", "", {}, "sha512-iYgNnGyeeJ4t6U11NpA/QiKy+PXn5Aa3Azg5qkwIFz1tBLllQrjjsk9yzD7IAK0naNU4JxdeDgqW9ov4u/hc4g=="],
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
"xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
@@ -1838,9 +2151,9 @@
"@ai-sdk/amazon-bedrock/aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="],
"@ai-sdk/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],
"@ai-sdk/gateway/@ai-sdk/provider": ["@ai-sdk/provider@2.0.0-beta.2", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-vqhtZA7R24q1XnmfmIb1fZSmHMIaJH1BVQ+0kFnNJgqWsc+V8i+yfetZ37gUc4fXATFmBuS/6O7+RPoHsZ2Fqg=="],
"@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
"@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0-beta.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.2", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-e6WSsgM01au04/1L/v5daXHn00eKjPBQXl3jq3BfvQbQ1jo8Rls2pvrdkyVc25jBW4TV4Zm+tw+v6NAh5NPXMA=="],
"@ampproject/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
@@ -1858,6 +2171,10 @@
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@grpc/proto-loader/long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
"@grpc/proto-loader/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
"@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
"@mdx-js/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
@@ -1868,10 +2185,24 @@
"@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/core": ["@opentelemetry/core@1.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "1.0.0", "semver": "^7.3.5" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-1+qvKilADnSFW4PiXy+f7D22pvfGVxepZ69GcbF8cTcbQTUt7w63xEBWn5f5j92x9I3c0sqbW1RUx5/a4wgzxA=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/resources": ["@opentelemetry/resources@1.0.0", "", { "dependencies": { "@opentelemetry/core": "1.0.0", "@opentelemetry/semantic-conventions": "1.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-ORP8F2LLcJEm5M3H24RmdlMdiDc70ySPushpkrAW34KZGdZXwkrFoFXZhhs5MUxPT+fLrTuBafXxZVr8eHtFuQ=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@1.0.0", "", { "dependencies": { "@opentelemetry/core": "1.0.0", "@opentelemetry/resources": "1.0.0", "@opentelemetry/semantic-conventions": "1.0.0", "lodash.merge": "^4.6.2" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-/rXoyQlDlJTJ4SOVAbP0Gpj89B8oZ2hJApYG2Dq5klkgFAtDifN8271TIzwtM8/ET8HUhgx9eyoUJi42LhIesg=="],
"@opentelemetry/sdk-metrics-base/@opentelemetry/core": ["@opentelemetry/core@1.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "1.0.0", "semver": "^7.3.5" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-1+qvKilADnSFW4PiXy+f7D22pvfGVxepZ69GcbF8cTcbQTUt7w63xEBWn5f5j92x9I3c0sqbW1RUx5/a4wgzxA=="],
"@opentelemetry/sdk-metrics-base/@opentelemetry/resources": ["@opentelemetry/resources@1.0.0", "", { "dependencies": { "@opentelemetry/core": "1.0.0", "@opentelemetry/semantic-conventions": "1.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.2" } }, "sha512-ORP8F2LLcJEm5M3H24RmdlMdiDc70ySPushpkrAW34KZGdZXwkrFoFXZhhs5MUxPT+fLrTuBafXxZVr8eHtFuQ=="],
"@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="],
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"ai/@ai-sdk/provider": ["@ai-sdk/provider@2.0.0-beta.2", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-vqhtZA7R24q1XnmfmIb1fZSmHMIaJH1BVQ+0kFnNJgqWsc+V8i+yfetZ37gUc4fXATFmBuS/6O7+RPoHsZ2Fqg=="],
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0-beta.10", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.2", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-e6WSsgM01au04/1L/v5daXHn00eKjPBQXl3jq3BfvQbQ1jo8Rls2pvrdkyVc25jBW4TV4Zm+tw+v6NAh5NPXMA=="],
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
@@ -1890,6 +2221,8 @@
"fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"gray-matter/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
@@ -1898,6 +2231,8 @@
"http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
"jaeger-client/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
"miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
"miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
@@ -1912,6 +2247,8 @@
"nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"opencode/@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.2.12", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ=="],
"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/hono": ["hono@4.7.4", "", {}, "sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg=="],
@@ -1930,6 +2267,8 @@
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
"protobufjs/long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
"router/path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="],
"sitemap/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
@@ -1992,12 +2331,30 @@
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"@grpc/proto-loader/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"@grpc/proto-loader/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.0.0", "", {}, "sha512-XCZ6ZSmc8FOspxKUU+Ow9UtJeSSRcS5rFBYGpjzix02U2v+X9ofjOjgNRnpvxlSvkccYIhdTuwcvNskmZ46SeA=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.0.0", "", {}, "sha512-XCZ6ZSmc8FOspxKUU+Ow9UtJeSSRcS5rFBYGpjzix02U2v+X9ofjOjgNRnpvxlSvkccYIhdTuwcvNskmZ46SeA=="],
"@opentelemetry/exporter-otlp-http/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.0.0", "", {}, "sha512-XCZ6ZSmc8FOspxKUU+Ow9UtJeSSRcS5rFBYGpjzix02U2v+X9ofjOjgNRnpvxlSvkccYIhdTuwcvNskmZ46SeA=="],
"@opentelemetry/sdk-metrics-base/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.0.0", "", {}, "sha512-XCZ6ZSmc8FOspxKUU+Ow9UtJeSSRcS5rFBYGpjzix02U2v+X9ofjOjgNRnpvxlSvkccYIhdTuwcvNskmZ46SeA=="],
"@opentelemetry/sdk-metrics-base/@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.0.0", "", {}, "sha512-XCZ6ZSmc8FOspxKUU+Ow9UtJeSSRcS5rFBYGpjzix02U2v+X9ofjOjgNRnpvxlSvkccYIhdTuwcvNskmZ46SeA=="],
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
"opencode/@ai-sdk/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],
"opencode/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
"opencontrol/@modelcontextprotocol/sdk/pkce-challenge": ["pkce-challenge@4.1.0", "", {}, "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ=="],
"opencontrol/@modelcontextprotocol/sdk/zod": ["zod@3.25.49", "", {}, "sha512-JMMPMy9ZBk3XFEdbM3iL1brx4NUSejd6xr3ELrrGEfGb355gjhiAWtG3K5o+AViV/3ZfkIrCzXsZn6SbLwTR8Q=="],
@@ -2068,6 +2425,20 @@
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
"@grpc/proto-loader/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"@grpc/proto-loader/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"@grpc/proto-loader/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"@grpc/proto-loader/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@grpc/proto-loader/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@grpc/proto-loader/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@grpc/proto-loader/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
}
}
+12
View File
@@ -46,3 +46,15 @@ new sst.cloudflare.x.Astro("Web", {
VITE_API_URL: api.url,
},
})
const OPENCODE_API_KEY = new sst.Secret("OPENCODE_API_KEY")
const ANTHROPIC_API_KEY = new sst.Secret("ANTHROPIC_API_KEY")
const OPENAI_API_KEY = new sst.Secret("OPENAI_API_KEY")
const ZHIPU_API_KEY = new sst.Secret("ZHIPU_API_KEY")
export const gateway = new sst.cloudflare.Worker("GatewayApi", {
domain: `api.gateway.${domain}`,
handler: "packages/function/src/gateway.ts",
url: true,
link: [OPENCODE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, ZHIPU_API_KEY],
})
-1
View File
@@ -1,6 +1,5 @@
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["./packages/plugin/src/example.ts"],
"mcp": {
"context7": {
"type": "remote",
+1 -1
View File
@@ -5,7 +5,7 @@
"type": "module",
"packageManager": "bun@1.2.14",
"scripts": {
"dev": "bun run packages/opencode/src/index.ts",
"dev": "bun run --conditions=development packages/opencode/src/index.ts",
"typecheck": "bun run --filter='*' typecheck",
"stainless": "./scripts/stainless",
"postinstall": "./script/hooks"
+8 -3
View File
@@ -1,17 +1,22 @@
{
"name": "@opencode/function",
"version": "0.3.113",
"version": "0.3.133",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"devDependencies": {
"@cloudflare/workers-types": "4.20250522.0",
"typescript": "catalog:",
"@types/node": "catalog:"
"@types/node": "catalog:",
"openai": "5.11.0",
"typescript": "catalog:"
},
"dependencies": {
"@ai-sdk/anthropic": "2.0.0",
"@ai-sdk/openai": "2.0.2",
"@ai-sdk/openai-compatible": "1.0.1",
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "22.0.0",
"ai": "catalog:",
"hono": "catalog:",
"jose": "6.0.11"
}
+499
View File
@@ -0,0 +1,499 @@
import { Hono, Context, Next } from "hono"
import { Resource } from "sst"
import { generateText, streamText } from "ai"
import { createAnthropic } from "@ai-sdk/anthropic"
import { createOpenAI } from "@ai-sdk/openai"
import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
import { type LanguageModelV2Prompt } from "@ai-sdk/provider"
import { type ChatCompletionCreateParamsBase } from "openai/resources/chat/completions"
type Env = {}
const auth = async (c: Context, next: Next) => {
const authHeader = c.req.header("authorization")
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return c.json(
{
error: {
message: "Missing API key.",
type: "invalid_request_error",
param: null,
code: "unauthorized",
},
},
401,
)
}
const apiKey = authHeader.split(" ")[1]
// Replace with your validation logic
if (apiKey !== Resource.OPENCODE_API_KEY.value) {
return c.json(
{
error: {
message: "Invalid API key.",
type: "invalid_request_error",
param: null,
code: "unauthorized",
},
},
401,
)
}
await next()
}
export default new Hono<{ Bindings: Env }>()
.get("/", (c) => c.text("Hello, world!"))
.post("/v1/chat/completions", auth, async (c) => {
try {
const body = await c.req.json<ChatCompletionCreateParamsBase>()
console.log(body)
const model = (() => {
const [provider, ...parts] = body.model.split("/")
const model = parts.join("/")
if (provider === "anthropic" && model === "claude-sonnet-4") {
return createAnthropic({
apiKey: Resource.ANTHROPIC_API_KEY.value,
})("claude-sonnet-4-20250514")
}
if (provider === "openai" && model === "gpt-4.1") {
return createOpenAI({
apiKey: Resource.OPENAI_API_KEY.value,
})("gpt-4.1")
}
if (provider === "zhipuai" && model === "glm-4.5-flash") {
return createOpenAICompatible({
name: "Zhipu AI",
baseURL: "https://api.z.ai/api/paas/v4",
apiKey: Resource.ZHIPU_API_KEY.value,
})("glm-4.5-flash")
}
throw new Error(`Unsupported provider: ${provider}`)
})()
const requestBody = transformOpenAIRequestToAiSDK()
return body.stream ? await handleStream() : await handleGenerate()
async function handleStream() {
const result = await streamText({
model,
...requestBody,
})
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
const id = `chatcmpl-${Date.now()}`
const created = Math.floor(Date.now() / 1000)
try {
for await (const chunk of result.fullStream) {
// TODO
//console.log("!!! CHUCK !!!", chunk);
switch (chunk.type) {
case "text-delta": {
const data = {
id,
object: "chat.completion.chunk",
created,
model: body.model,
choices: [
{
index: 0,
delta: {
content: chunk.text,
},
finish_reason: null,
},
],
}
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
break
}
case "reasoning-delta": {
const data = {
id,
object: "chat.completion.chunk",
created,
model: body.model,
choices: [
{
index: 0,
delta: {
reasoning_content: chunk.text,
},
finish_reason: null,
},
],
}
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
break
}
case "tool-call": {
const data = {
id,
object: "chat.completion.chunk",
created,
model: body.model,
choices: [
{
index: 0,
delta: {
tool_calls: [
{
id: chunk.toolCallId,
type: "function",
function: {
name: chunk.toolName,
arguments: JSON.stringify(chunk.input),
},
},
],
},
finish_reason: null,
},
],
}
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
break
}
case "error": {
const data = {
id,
object: "chat.completion.chunk",
created,
model: body.model,
error: {
message: chunk.error,
type: "server_error",
},
}
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
controller.enqueue(encoder.encode("data: [DONE]\n\n"))
controller.close()
break
}
case "finish": {
const finishReason =
{
stop: "stop",
length: "length",
"content-filter": "content_filter",
"tool-calls": "tool_calls",
error: "stop",
other: "stop",
unknown: "stop",
}[chunk.finishReason] || "stop"
const data = {
id,
object: "chat.completion.chunk",
created,
model: body.model,
choices: [
{
index: 0,
delta: {},
finish_reason: finishReason,
},
],
usage: {
prompt_tokens: chunk.totalUsage.inputTokens,
completion_tokens: chunk.totalUsage.outputTokens,
total_tokens: chunk.totalUsage.totalTokens,
completion_tokens_details: {
reasoning_tokens: chunk.totalUsage.reasoningTokens,
},
prompt_tokens_details: {
cached_tokens: chunk.totalUsage.cachedInputTokens,
},
},
}
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
controller.enqueue(encoder.encode("data: [DONE]\n\n"))
controller.close()
break
}
//case "stream-start":
//case "response-metadata":
case "start-step":
case "finish-step":
case "text-start":
case "text-end":
case "reasoning-start":
case "reasoning-end":
case "tool-input-start":
case "tool-input-delta":
case "tool-input-end":
case "raw":
default:
// Log unknown chunk types for debugging
console.warn(`Unknown chunk type: ${(chunk as any).type}`)
break
}
}
} catch (error) {
controller.error(error)
}
},
})
return new Response(stream, {
headers: {
"Content-Type": "text/plain; charset=utf-8",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
})
}
async function handleGenerate() {
const response = await generateText({
model,
...requestBody,
})
return c.json({
id: `chatcmpl-${Date.now()}`,
object: "chat.completion" as const,
created: Math.floor(Date.now() / 1000),
model: body.model,
choices: [
{
index: 0,
message: {
role: "assistant" as const,
content: response.content?.find((c) => c.type === "text")?.text ?? "",
reasoning_content: response.content?.find((c) => c.type === "reasoning")?.text,
tool_calls: response.content
?.filter((c) => c.type === "tool-call")
.map((toolCall) => ({
id: toolCall.toolCallId,
type: "function" as const,
function: {
name: toolCall.toolName,
arguments: toolCall.input,
},
})),
},
finish_reason:
(
{
stop: "stop",
length: "length",
"content-filter": "content_filter",
"tool-calls": "tool_calls",
error: "stop",
other: "stop",
unknown: "stop",
} as const
)[response.finishReason] || "stop",
},
],
usage: {
prompt_tokens: response.usage?.inputTokens,
completion_tokens: response.usage?.outputTokens,
total_tokens: response.usage?.totalTokens,
completion_tokens_details: {
reasoning_tokens: response.usage?.reasoningTokens,
},
prompt_tokens_details: {
cached_tokens: response.usage?.cachedInputTokens,
},
},
})
}
function transformOpenAIRequestToAiSDK() {
const prompt = transformMessages()
return {
prompt,
maxOutputTokens: body.max_tokens ?? body.max_completion_tokens ?? undefined,
temperature: body.temperature ?? undefined,
topP: body.top_p ?? undefined,
frequencyPenalty: body.frequency_penalty ?? undefined,
presencePenalty: body.presence_penalty ?? undefined,
providerOptions: body.reasoning_effort
? {
anthropic: {
reasoningEffort: body.reasoning_effort,
},
}
: undefined,
stopSequences: (typeof body.stop === "string" ? [body.stop] : body.stop) ?? undefined,
responseFormat: (() => {
if (!body.response_format) return { type: "text" }
if (body.response_format.type === "json_schema")
return {
type: "json",
schema: body.response_format.json_schema.schema,
name: body.response_format.json_schema.name,
description: body.response_format.json_schema.description,
}
if (body.response_format.type === "json_object") return { type: "json" }
throw new Error("Unsupported response format")
})(),
seed: body.seed ?? undefined,
}
function transformTools() {
const { tools, tool_choice } = body
if (!tools || tools.length === 0) {
return { tools: undefined, toolChoice: undefined }
}
const aiSdkTools = tools.reduce(
(acc, tool) => {
acc[tool.function.name] = {
type: "function" as const,
name: tool.function.name,
description: tool.function.description,
inputSchema: tool.function.parameters,
}
return acc
},
{} as Record<string, any>,
)
let aiSdkToolChoice
if (tool_choice == null) {
aiSdkToolChoice = undefined
} else if (tool_choice === "auto") {
aiSdkToolChoice = "auto"
} else if (tool_choice === "none") {
aiSdkToolChoice = "none"
} else if (tool_choice === "required") {
aiSdkToolChoice = "required"
} else if (tool_choice.type === "function") {
aiSdkToolChoice = {
type: "tool",
toolName: tool_choice.function.name,
}
}
return { tools: aiSdkTools, toolChoice: aiSdkToolChoice }
}
function transformMessages() {
const { messages } = body
const prompt: LanguageModelV2Prompt = []
for (const message of messages) {
switch (message.role) {
case "system": {
prompt.push({
role: "system",
content: message.content as string,
})
break
}
case "user": {
if (typeof message.content === "string") {
prompt.push({
role: "user",
content: [{ type: "text", text: message.content }],
})
} else {
const content = message.content.map((part) => {
switch (part.type) {
case "text":
return { type: "text" as const, text: part.text }
case "image_url":
return {
type: "file" as const,
mediaType: "image/jpeg" as const,
data: part.image_url.url,
}
default:
throw new Error(`Unsupported content part type: ${(part as any).type}`)
}
})
prompt.push({
role: "user",
content,
})
}
break
}
case "assistant": {
const content: Array<
| { type: "text"; text: string }
| {
type: "tool-call"
toolCallId: string
toolName: string
input: any
}
> = []
if (message.content) {
content.push({
type: "text",
text: message.content as string,
})
}
if (message.tool_calls) {
for (const toolCall of message.tool_calls) {
content.push({
type: "tool-call",
toolCallId: toolCall.id,
toolName: toolCall.function.name,
input: JSON.parse(toolCall.function.arguments),
})
}
}
prompt.push({
role: "assistant",
content,
})
break
}
case "tool": {
prompt.push({
role: "tool",
content: [
{
type: "tool-result",
toolName: "placeholder",
toolCallId: message.tool_call_id,
output: {
type: "text",
value: message.content as string,
},
},
],
})
break
}
default: {
throw new Error(`Unsupported message role: ${message.role}`)
}
}
}
return prompt
}
}
} catch (error: any) {
return c.json({ error: { message: error.message } }, 500)
}
})
.all("*", (c) => c.text("Not Found"))
+17
View File
@@ -6,6 +6,10 @@
import "sst"
declare module "sst" {
export interface Resource {
"ANTHROPIC_API_KEY": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string
@@ -14,10 +18,22 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"OPENAI_API_KEY": {
"type": "sst.sst.Secret"
"value": string
}
"OPENCODE_API_KEY": {
"type": "sst.sst.Secret"
"value": string
}
"Web": {
"type": "sst.cloudflare.Astro"
"url": string
}
"ZHIPU_API_KEY": {
"type": "sst.sst.Secret"
"value": string
}
}
}
// cloudflare
@@ -26,6 +42,7 @@ declare module "sst" {
export interface Resource {
"Api": cloudflare.Service
"Bucket": cloudflare.R2Bucket
"GatewayApi": cloudflare.Service
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="white"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="white"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="white"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="white"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="white"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="white"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 981 B

+12
View File
@@ -0,0 +1,12 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="black"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="black"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="black"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="black"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="black"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="black"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 981 B

+18
View File
@@ -0,0 +1,18 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 16.5H24.5V33H8.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M48.5 16.5H64.5V33H48.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M120.5 16.5H136.5V33H120.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M160.5 16.5H176.5V33H160.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M192.5 16.5H208.5V33H192.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M232.5 16.5H248.5V33H232.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="white" fill-opacity="0.5"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="white" fill-opacity="0.95"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+18
View File
@@ -0,0 +1,18 @@
<svg width="288" height="50" viewBox="0 0 288 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 16.5H24V33H8V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M48 16.5H64V33H48V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M120 16.5H136V33H120V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M160 16.5H176V33H160V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M192 16.5H208V33H192V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M232 16.5H248V33H232V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M264 0H288V8.5H272V16.5H288V25H272V33H288V41.5H264V0Z" fill="black" fill-opacity="0.95"/>
<path d="M248 0H224V41.5H248V33H232V8.5H248V0Z" fill="black" fill-opacity="0.95"/>
<path d="M256 8.5H248V33H256V8.5Z" fill="black" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184 0H216V41.5H184V0ZM208 8.5H192V33H208V8.5Z" fill="black" fill-opacity="0.95"/>
<path d="M144 8.5H136V41.5H144V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M136 0H112V41.5H120V8.5H136V0Z" fill="black" fill-opacity="0.55"/>
<path d="M80 0H104V8.5H88V16.5H104V25H88V33H104V41.5H80V0Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40 0H72V41.5H48V49.5H40V0ZM64 8.5H48V33H64V8.5Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H32V41.5955H0V0ZM24 8.5H8V33H24V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M152 0H176V8.5H160V33H176V41.5H152V0Z" fill="black" fill-opacity="0.95"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 13H35V58H0V13ZM26.25 22.1957H8.75V48.701H26.25V22.1957Z" fill="white"/>
<path d="M43.75 13H70V22.1957H52.5V48.701H70V57.8967H43.75V13Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 306 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 13H35V58H0V13ZM26.25 22.1957H8.75V48.701H26.25V22.1957Z" fill="black"/>
<path d="M43.75 13H70V22.1957H52.5V48.701H70V57.8967H43.75V13Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 306 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="64" height="42" viewBox="0 0 64 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H32V41.5955H0V0ZM24 8.5H8V33H24V8.5Z" fill="white"/>
<path d="M40 0H64V8.5H48V33H64V41.5H40V0Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 267 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="64" height="42" viewBox="0 0 64 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H32V41.5955H0V0ZM24 8.5H8V33H24V8.5Z" fill="black"/>
<path d="M40 0H64V8.5H48V33H64V41.5H40V0Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 267 B

-13
View File
@@ -17,19 +17,6 @@
- **Error handling**: Use Result patterns, avoid throwing exceptions in tools
- **File structure**: Namespace-based organization (e.g., `Tool.define()`, `Session.create()`)
## IMPORTANT
- Try to keep things in one function unless composable or reusable
- DO NOT do unnecessary destructuring of variables
- DO NOT use `else` statements unless necessary
- DO NOT use `try`/`catch` if it can be avoided
- AVOID `try`/`catch` where possible
- AVOID `else` statements
- AVOID using `any` type
- AVOID `let` statements
- PREFER single word variable names where possible
- Use as many bun apis as possible like Bun.file()
## Architecture
- **Tools**: Implement `Tool.Info` interface with `execute()` method
+9 -2
View File
@@ -1,12 +1,12 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.3.113",
"version": "0.3.133",
"name": "opencode",
"type": "module",
"private": true,
"scripts": {
"typecheck": "tsc --noEmit",
"dev": "bun run ./src/index.ts"
"dev": "bun run --conditions=development ./src/index.ts"
},
"bin": {
"opencode": "./bin/opencode"
@@ -38,6 +38,13 @@
"@openauthjs/openauth": "0.4.3",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/sdk": "workspace:*",
"@opentelemetry/auto-instrumentations-node": "0.62.0",
"@opentelemetry/exporter-jaeger": "2.0.1",
"@opentelemetry/exporter-otlp-http": "0.26.0",
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
"@opentelemetry/instrumentation-fetch": "0.203.0",
"@opentelemetry/sdk-node": "0.203.0",
"@opentelemetry/sdk-trace-node": "2.0.1",
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
+30 -9
View File
@@ -10,13 +10,16 @@ export namespace Agent {
export const Info = z
.object({
name: z.string(),
description: z.string().optional(),
mode: z.union([z.literal("subagent"), z.literal("primary"), z.literal("all")]),
topP: z.number().optional(),
temperature: z.number().optional(),
model: z
.object({
modelID: z.string(),
providerID: z.string(),
})
.optional(),
description: z.string(),
prompt: z.string().optional(),
tools: z.record(z.boolean()),
})
@@ -24,6 +27,7 @@ export namespace Agent {
ref: "Agent",
})
export type Info = z.infer<typeof Info>
const state = App.state("agent", async () => {
const cfg = await Config.get()
const result: Record<string, Info> = {
@@ -35,22 +39,36 @@ export namespace Agent {
todoread: false,
todowrite: false,
},
mode: "subagent",
},
build: {
name: "build",
tools: {},
mode: "primary",
},
plan: {
name: "plan",
tools: {
write: false,
edit: false,
patch: false,
},
mode: "primary",
},
}
for (const [key, value] of Object.entries(cfg.agent ?? {})) {
if (value.disable) continue
if (value.disable) {
delete result[key]
continue
}
let item = result[key]
if (!item)
item = result[key] = {
name: key,
description: "",
tools: {
todowrite: false,
todoread: false,
},
mode: "all",
tools: {},
}
const model = value.model ?? cfg.model
if (model) item.model = Provider.parseModel(model)
if (value.model) item.model = Provider.parseModel(value.model)
if (value.prompt) item.prompt = value.prompt
if (value.tools)
item.tools = {
@@ -58,6 +76,9 @@ export namespace Agent {
...value.tools,
}
if (value.description) item.description = value.description
if (value.temperature != undefined) item.temperature = value.temperature
if (value.top_p != undefined) item.topP = value.top_p
if (value.mode) item.mode = value.mode
}
return result
})
+1 -1
View File
@@ -641,7 +641,7 @@ export const GithubRunCommand = cmd({
messageID: Identifier.ascending("message"),
providerID,
modelID,
mode: "build",
agent: "build",
parts: [
{
id: Identifier.ascending("part"),
+19 -9
View File
@@ -8,8 +8,8 @@ import { Flag } from "../../flag/flag"
import { Config } from "../../config/config"
import { bootstrap } from "../bootstrap"
import { MessageV2 } from "../../session/message-v2"
import { Mode } from "../../session/mode"
import { Identifier } from "../../id/id"
import { Agent } from "../../agent/agent"
const TOOL: Record<string, [string, string]> = {
todowrite: ["Todo", UI.Style.TEXT_WARNING_BOLD],
@@ -54,9 +54,9 @@ export const RunCommand = cmd({
alias: ["m"],
describe: "model to use in the format of provider/model",
})
.option("mode", {
.option("agent", {
type: "string",
describe: "mode to use",
describe: "agent to use",
})
},
handler: async (args) => {
@@ -103,7 +103,19 @@ export const RunCommand = cmd({
}
UI.empty()
const { providerID, modelID } = args.model ? Provider.parseModel(args.model) : await Provider.defaultModel()
const agent = await (async () => {
if (args.agent) return Agent.get(args.agent)
const build = Agent.get("build")
if (build) return build
return Agent.list().then((x) => x[0])
})()
const { providerID, modelID } = await (() => {
if (args.model) return Provider.parseModel(args.model)
if (agent.model) return agent.model
return Provider.defaultModel()
})()
UI.println(UI.Style.TEXT_NORMAL_BOLD + "@ ", UI.Style.TEXT_NORMAL + `${providerID}/${modelID}`)
UI.empty()
@@ -156,19 +168,17 @@ export const RunCommand = cmd({
UI.error(err)
})
const mode = args.mode ? await Mode.get(args.mode) : await Mode.list().then((x) => x[0])
const messageID = Identifier.ascending("message")
const result = await Session.chat({
sessionID: session.id,
messageID,
...(mode.model
? mode.model
...(agent.model
? agent.model
: {
providerID,
modelID,
}),
mode: mode.name,
agent: agent.name,
parts: [
{
id: Identifier.ascending("part"),
+2 -2
View File
@@ -11,8 +11,8 @@ import { Config } from "../../config/config"
import { Bus } from "../../bus"
import { Log } from "../../util/log"
import { FileWatcher } from "../../file/watch"
import { Mode } from "../../session/mode"
import { Ide } from "../../ide"
import { Agent } from "../../agent/agent"
declare global {
const OPENCODE_TUI_PATH: string
@@ -115,7 +115,7 @@ export const TuiCommand = cmd({
CGO_ENABLED: "0",
OPENCODE_SERVER: server.url.toString(),
OPENCODE_APP_INFO: JSON.stringify(app),
OPENCODE_MODES: JSON.stringify(await Mode.list()),
OPENCODE_AGENTS: JSON.stringify(await Agent.list()),
},
onExit: () => {
server.stop()
+55 -25
View File
@@ -1,5 +1,6 @@
import { Log } from "../util/log"
import path from "path"
import os from "os"
import { z } from "zod"
import { App } from "../app/app"
import { Filesystem } from "../util/filesystem"
@@ -82,7 +83,7 @@ export namespace Config {
...md.data,
prompt: md.content.trim(),
}
const parsed = Mode.safeParse(config)
const parsed = Agent.safeParse(config)
if (parsed.success) {
result.mode = mergeDeep(result.mode, {
[config.name]: parsed.data,
@@ -91,6 +92,23 @@ export namespace Config {
}
throw new InvalidError({ path: item }, { cause: parsed.error })
}
// Migrate deprecated mode field to agent field
for (const [name, mode] of Object.entries(result.mode)) {
result.agent = mergeDeep(result.agent ?? {}, {
[name]: {
...mode,
mode: "primary" as const,
},
})
}
result.plugin = result.plugin || []
result.plugin.push(
...[
...(await Filesystem.globUp("plugin/*.ts", Global.Path.config, Global.Path.config)),
...(await Filesystem.globUp(".opencode/plugin/*.ts", app.path.cwd, app.path.root)),
].map((x) => "file://" + x),
)
// Handle migration from autoshare to share field
if (result.autoshare === true && !result.share) {
@@ -99,6 +117,12 @@ export namespace Config {
if (result.keybinds?.messages_revert && !result.keybinds.messages_undo) {
result.keybinds.messages_undo = result.keybinds.messages_revert
}
if (result.keybinds?.switch_mode && !result.keybinds.switch_agent) {
result.keybinds.switch_agent = result.keybinds.switch_mode
}
if (result.keybinds?.switch_mode_reverse && !result.keybinds.switch_agent_reverse) {
result.keybinds.switch_agent_reverse = result.keybinds.switch_mode_reverse
}
if (!result.username) {
const os = await import("os")
@@ -140,7 +164,7 @@ export namespace Config {
export const Mcp = z.discriminatedUnion("type", [McpLocal, McpRemote])
export type Mcp = z.infer<typeof Mcp>
export const Mode = z
export const Agent = z
.object({
model: z.string().optional(),
temperature: z.number().optional(),
@@ -148,24 +172,26 @@ export namespace Config {
prompt: z.string().optional(),
tools: z.record(z.string(), z.boolean()).optional(),
disable: z.boolean().optional(),
description: z.string().optional().describe("Description of when to use the agent"),
mode: z.union([z.literal("subagent"), z.literal("primary"), z.literal("all")]).optional(),
})
.openapi({
ref: "ModeConfig",
ref: "AgentConfig",
})
export type Mode = z.infer<typeof Mode>
export const Agent = Mode.extend({
description: z.string(),
}).openapi({
ref: "AgentConfig",
})
export type Agent = z.infer<typeof Agent>
export const Keybinds = z
.object({
leader: z.string().optional().default("ctrl+x").describe("Leader key for keybind combinations"),
app_help: z.string().optional().default("<leader>h").describe("Show help dialog"),
switch_mode: z.string().optional().default("tab").describe("Next mode"),
switch_mode_reverse: z.string().optional().default("shift+tab").describe("Previous Mode"),
switch_mode: z.string().optional().default("none").describe("@deprecated use switch_agent. Next mode"),
switch_mode_reverse: z
.string()
.optional()
.default("none")
.describe("@deprecated use switch_agent_reverse. Previous mode"),
switch_agent: z.string().optional().default("tab").describe("Next agent"),
switch_agent_reverse: z.string().optional().default("shift+tab").describe("Previous agent"),
editor_open: z.string().optional().default("<leader>e").describe("Open external editor"),
session_export: z.string().optional().default("<leader>x").describe("Export session to editor"),
session_new: z.string().optional().default("<leader>n").describe("Create a new session"),
@@ -215,7 +241,7 @@ export namespace Config {
})
export type Layout = z.infer<typeof Layout>
export const Permission = z.union([z.literal("ask"), z.literal("allow")])
export const Permission = z.union([z.literal("ask"), z.literal("allow"), z.literal("deny")])
export type Permission = z.infer<typeof Permission>
export const Info = z
@@ -224,6 +250,7 @@ export namespace Config {
theme: z.string().optional().describe("Theme name to use for the interface"),
keybinds: Keybinds.optional().describe("Custom keybind configurations"),
plugin: z.string().array().optional(),
snapshot: z.boolean().optional(),
share: z
.enum(["manual", "auto", "disabled"])
.optional()
@@ -239,9 +266,7 @@ export namespace Config {
model: z.string().describe("Model to use in the format of provider/model, eg anthropic/claude-2").optional(),
small_model: z
.string()
.describe(
"Small model to use for tasks like summarization and title generation in the format of provider/model",
)
.describe("Small model to use for tasks like title generation in the format of provider/model")
.optional(),
username: z
.string()
@@ -249,19 +274,21 @@ export namespace Config {
.describe("Custom username to display in conversations instead of system username"),
mode: z
.object({
build: Mode.optional(),
plan: Mode.optional(),
build: Agent.optional(),
plan: Agent.optional(),
})
.catchall(Mode)
.catchall(Agent)
.optional()
.describe("Modes configuration, see https://opencode.ai/docs/modes"),
.describe("@deprecated Use `agent` field instead."),
agent: z
.object({
plan: Agent.optional(),
build: Agent.optional(),
general: Agent.optional(),
})
.catchall(Agent)
.optional()
.describe("Modes configuration, see https://opencode.ai/docs/modes"),
.describe("Agent configuration, see https://opencode.ai/docs/agent"),
provider: z
.record(
ModelsDev.Provider.partial()
@@ -403,7 +430,10 @@ export namespace Config {
if (lineIndex !== -1 && lines[lineIndex].trim().startsWith("//")) {
continue // Skip if line is commented
}
const filePath = match.replace(/^\{file:/, "").replace(/\}$/, "")
let filePath = match.replace(/^\{file:/, "").replace(/\}$/, "")
if (filePath.startsWith("~/")) {
filePath = path.join(os.homedir(), filePath.slice(2))
}
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(configDir, filePath)
const fileContent = (await Bun.file(resolvedPath).text()).trim()
// escape newlines/quotes, strip outer quotes
@@ -445,9 +475,9 @@ export namespace Config {
if (data.plugin) {
for (let i = 0; i < data.plugin?.length; i++) {
const plugin = data.plugin[i]
if (typeof plugin === "string") {
data.plugin[i] = path.resolve(path.dirname(filepath), plugin)
}
try {
data.plugin[i] = import.meta.resolve(plugin, filepath)
} catch (err) {}
}
}
return data
+3 -3
View File
@@ -1,4 +1,6 @@
import "zod-openapi/extend"
import { Trace } from "./trace"
Trace.init()
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import { RunCommand } from "./cli/cmd/run"
@@ -18,9 +20,6 @@ import { DebugCommand } from "./cli/cmd/debug"
import { StatsCommand } from "./cli/cmd/stats"
import { McpCommand } from "./cli/cmd/mcp"
import { GithubCommand } from "./cli/cmd/github"
import { Trace } from "./trace"
Trace.init()
const cancel = new AbortController()
@@ -83,6 +82,7 @@ const cli = yargs(hideBin(process.argv))
if (msg.startsWith("Unknown argument") || msg.startsWith("Not enough non-option arguments")) {
cli.showHelp("log")
}
process.exit(1)
})
.strict()
+1
View File
@@ -67,6 +67,7 @@ export namespace LSP {
}
servers[name] = {
...existing,
root: existing?.root ?? (async (_file, app) => app.path.root),
extensions: item.extensions ?? existing.extensions,
spawn: async (_app, root) => {
return {
+15 -31
View File
@@ -5,7 +5,7 @@ import { Bus } from "../bus"
import { Log } from "../util/log"
import { createOpencodeClient } from "@opencode-ai/sdk"
import { Server } from "../server/server"
import { pathOr } from "remeda"
import { BunProc } from "../bun"
export namespace Plugin {
const log = Log.create({ service: "plugin" })
@@ -17,8 +17,12 @@ export namespace Plugin {
})
const config = await Config.get()
const hooks = []
for (const plugin of config.plugin ?? []) {
for (let plugin of config.plugin ?? []) {
log.info("loading plugin", { path: plugin })
if (!plugin.startsWith("file://")) {
const [pkg, version] = plugin.split("@")
plugin = await BunProc.install(pkg, version ?? "latest")
}
const mod = await import(plugin)
for (const [_name, fn] of Object.entries<PluginInstance>(mod)) {
const init = await fn({
@@ -35,38 +39,18 @@ export namespace Plugin {
}
})
type Path<T, Prefix extends string = ""> = T extends object
? {
[K in keyof T]: K extends string
? T[K] extends Function | undefined
? `${Prefix}${K}`
: Path<T[K], `${Prefix}${K}.`>
: never
}[keyof T]
: never
export type FunctionFromKey<T, P extends Path<T>> = P extends `${infer K}.${infer R}`
? K extends keyof T
? R extends Path<T[K]>
? FunctionFromKey<T[K], R>
: never
: never
: P extends keyof T
? T[P]
: never
export async function trigger<
Name extends Path<Required<Hooks>>,
Input = Parameters<FunctionFromKey<Required<Hooks>, Name>>[0],
Output = Parameters<FunctionFromKey<Required<Hooks>, Name>>[1],
>(fn: Name, input: Input, output: Output): Promise<Output> {
if (!fn) return output
const path = fn.split(".")
Name extends keyof Required<Hooks>,
Input = Parameters<Required<Hooks>[Name]>[0],
Output = Parameters<Required<Hooks>[Name]>[1],
>(name: Name, input: Input, output: Output): Promise<Output> {
if (!name) return output
for (const hook of await state().then((x) => x.hooks)) {
// @ts-expect-error
const fn = pathOr(hook, path, undefined)
const fn = hook[name]
if (!fn) continue
// @ts-expect-error
// @ts-expect-error if you feel adventurous, please fix the typing, make sure to bump the try-counter if you
// give up.
// try-counter: 2
await fn(input, output)
}
return output
+1 -1
View File
@@ -77,4 +77,4 @@ export namespace ModelsDev {
}
}
setInterval(() => ModelsDev.refresh(), 60 * 1000).unref()
setInterval(() => ModelsDev.refresh(), 60 * 1000 * 60).unref()
+14 -14
View File
@@ -97,7 +97,7 @@ export namespace Provider {
Array.isArray(msg.content) && msg.content.some((part: any) => part.type === "image_url"),
)
}
} catch {}
} catch { }
const headers: Record<string, string> = {
...init.headers,
...copilot.HEADERS,
@@ -283,26 +283,26 @@ export namespace Provider {
cost:
!model.cost && !existing?.cost
? {
input: 0,
output: 0,
cache_read: 0,
cache_write: 0,
}
input: 0,
output: 0,
cache_read: 0,
cache_write: 0,
}
: {
cache_read: 0,
cache_write: 0,
...existing?.cost,
...model.cost,
},
cache_read: 0,
cache_write: 0,
...existing?.cost,
...model.cost,
},
options: {
...existing?.options,
...model.options,
},
limit: model.limit ??
existing?.limit ?? {
context: 0,
output: 0,
},
context: 0,
output: 0,
},
}
parsed.models[modelID] = parsedModel
}
+36 -8
View File
@@ -16,10 +16,10 @@ import { Config } from "../config/config"
import { File } from "../file"
import { LSP } from "../lsp"
import { MessageV2 } from "../session/message-v2"
import { Mode } from "../session/mode"
import { callTui, TuiRoute } from "./tui"
import { Permission } from "../permission"
import { lazy } from "../util/lazy"
import { Agent } from "../agent/agent"
const ERRORS = {
400: {
@@ -219,6 +219,34 @@ export namespace Server {
return c.json(sessions)
},
)
.get(
"/session/:id",
describeRoute({
description: "Get session",
operationId: "session.get",
responses: {
200: {
description: "Get session",
content: {
"application/json": {
schema: resolver(Session.Info),
},
},
},
},
}),
zValidator(
"param",
z.object({
id: z.string(),
}),
),
async (c) => {
const sessionID = c.req.valid("param").id
const session = await Session.get(sessionID)
return c.json(session)
},
)
.post(
"/session",
describeRoute({
@@ -844,23 +872,23 @@ export namespace Server {
},
)
.get(
"/mode",
"/agent",
describeRoute({
description: "List all modes",
operationId: "app.modes",
description: "List all agents",
operationId: "app.agents",
responses: {
200: {
description: "List of modes",
description: "List of agents",
content: {
"application/json": {
schema: resolver(Mode.Info.array()),
schema: resolver(Agent.Info.array()),
},
},
},
},
}),
async (c) => {
const modes = await Mode.list()
const modes = await Agent.list()
return c.json(modes)
},
)
@@ -999,7 +1027,7 @@ export namespace Server {
.post(
"/tui/execute-command",
describeRoute({
description: "Execute a TUI command (e.g. switch_mode)",
description: "Execute a TUI command (e.g. switch_agent)",
operationId: "tui.executeCommand",
responses: {
200: {
+123 -72
View File
@@ -36,18 +36,29 @@ import { NamedError } from "../util/error"
import { SystemPrompt } from "./system"
import { FileTime } from "../file/time"
import { MessageV2 } from "./message-v2"
import { Mode } from "./mode"
import { LSP } from "../lsp"
import { ReadTool } from "../tool/read"
import { mergeDeep, pipe, splitWhen } from "remeda"
import { ToolRegistry } from "../tool/registry"
import { Plugin } from "../plugin"
import { Agent } from "../agent/agent"
export namespace Session {
const log = Log.create({ service: "session" })
const OUTPUT_TOKEN_MAX = 32_000
const parentSessionTitlePrefix = "New session - "
const childSessionTitlePrefix = "Child session - "
function createDefaultTitle(isChild = false) {
return (isChild ? childSessionTitlePrefix : parentSessionTitlePrefix) + new Date().toISOString()
}
function isDefaultTitle(title: string) {
return title.startsWith(parentSessionTitlePrefix)
}
export const Info = z
.object({
id: Identifier.schema("session"),
@@ -121,6 +132,7 @@ export namespace Session {
const sessions = new Map<string, Info>()
const messages = new Map<string, MessageV2.Info[]>()
const pending = new Map<string, AbortController>()
const autoCompacting = new Map<string, boolean>()
const queued = new Map<
string,
{
@@ -136,6 +148,7 @@ export namespace Session {
sessions,
messages,
pending,
autoCompacting,
queued,
}
},
@@ -151,7 +164,7 @@ export namespace Session {
id: Identifier.descending("session"),
version: Installation.VERSION,
parentID,
title: (parentID ? "Child session - " : "New Session - ") + new Date().toISOString(),
title: createDefaultTitle(!!parentID),
time: {
created: Date.now(),
updated: Date.now(),
@@ -309,9 +322,9 @@ export namespace Session {
for (const child of await children(sessionID)) {
await remove(child.id, false)
}
await unshare(sessionID).catch(() => {})
await Storage.remove(`session/info/${sessionID}`).catch(() => {})
await Storage.removeDir(`session/message/${sessionID}/`).catch(() => {})
await unshare(sessionID).catch(() => { })
await Storage.remove(`session/info/${sessionID}`).catch(() => { })
await Storage.removeDir(`session/message/${sessionID}/`).catch(() => { })
state().sessions.delete(sessionID)
state().messages.delete(sessionID)
if (emitEvent) {
@@ -344,7 +357,7 @@ export namespace Session {
messageID: Identifier.schema("message").optional(),
providerID: z.string(),
modelID: z.string(),
mode: z.string().optional(),
agent: z.string().optional(),
system: z.string().optional(),
tools: z.record(z.boolean()).optional(),
parts: z.array(
@@ -369,6 +382,16 @@ export namespace Session {
.openapi({
ref: "FilePartInput",
}),
MessageV2.AgentPart.omit({
messageID: true,
sessionID: true,
})
.partial({
id: true,
})
.openapi({
ref: "AgentPartInput",
}),
]),
),
})
@@ -380,7 +403,7 @@ export namespace Session {
const l = log.clone().tag("session", input.sessionID)
l.info("chatting")
const inputMode = input.mode ?? "build"
const inputAgent = input.agent ?? "build"
// Process revert cleanup first, before creating new messages
const session = await get(input.sessionID)
@@ -500,7 +523,7 @@ export namespace Session {
sessionID: input.sessionID,
abort: new AbortController().signal,
messageID: userMsg.id,
metadata: async () => {},
metadata: async () => { },
}),
)
return [
@@ -553,6 +576,28 @@ export namespace Session {
]
}
}
if (part.type === "agent") {
return [
{
id: Identifier.ascending("part"),
...part,
messageID: userMsg.id,
sessionID: input.sessionID,
},
{
id: Identifier.ascending("part"),
messageID: userMsg.id,
sessionID: input.sessionID,
type: "text",
synthetic: true,
text:
"Use the above message and context to generate a prompt and call the task tool with subagent: " +
part.name,
},
]
}
return [
{
id: Identifier.ascending("part"),
@@ -563,7 +608,7 @@ export namespace Session {
]
}),
).then((x) => x.flat())
if (inputMode === "plan")
if (inputAgent === "plan")
userParts.push({
id: Identifier.ascending("part"),
messageID: userMsg.id,
@@ -587,7 +632,7 @@ export namespace Session {
// mark session as updated
// used for session list sorting (indicates when session was most recently interacted with)
await update(input.sessionID, (_draft) => {})
await update(input.sessionID, (_draft) => { })
if (isLocked(input.sessionID)) {
return new Promise((resolve) => {
@@ -614,6 +659,8 @@ export namespace Session {
const tokens =
previous.tokens.input + previous.tokens.cache.read + previous.tokens.cache.write + previous.tokens.output
if (model.info.limit.context && tokens > Math.max((model.info.limit.context - outputLimit) * 0.9, 0)) {
state().autoCompacting.set(input.sessionID, true)
await summarize({
sessionID: input.sessionID,
providerID: input.providerID,
@@ -622,13 +669,12 @@ export namespace Session {
return chat(input)
}
}
using abort = lock(input.sessionID)
const lastSummary = msgs.findLast((msg) => msg.info.role === "assistant" && msg.info.summary === true)
if (lastSummary) msgs = msgs.filter((msg) => msg.info.id >= lastSummary.info.id)
if (msgs.length === 1 && !session.parentID) {
if (msgs.length === 1 && !session.parentID && isDefaultTitle(session.title)) {
const small = (await Provider.getSmallModel(input.providerID)) ?? model
generateText({
maxOutputTokens: small.info.reasoning ? 1024 : 20,
@@ -666,15 +712,15 @@ export namespace Session {
draft.title = title.trim()
})
})
.catch(() => {})
.catch(() => { })
}
const mode = await Mode.get(inputMode)
const agent = await Agent.get(inputAgent)
let system = SystemPrompt.header(input.providerID)
system.push(
...(() => {
if (input.system) return [input.system]
if (mode.prompt) return [mode.prompt]
if (agent.prompt) return [agent.prompt]
return SystemPrompt.provider(input.modelID)
})(),
)
@@ -688,7 +734,7 @@ export namespace Session {
id: Identifier.ascending("message"),
role: "assistant",
system,
mode: inputMode,
mode: inputAgent,
path: {
cwd: app.path.cwd,
root: app.path.root,
@@ -713,8 +759,8 @@ export namespace Session {
const processor = createProcessor(assistantMsg, model.info)
const enabledTools = pipe(
mode.tools,
mergeDeep(ToolRegistry.enabled(input.providerID, input.modelID)),
agent.tools,
mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID)),
mergeDeep(input.tools ?? {}),
)
for (const item of await ToolRegistry.tools(input.providerID, input.modelID)) {
@@ -735,10 +781,9 @@ export namespace Session {
args,
},
)
await processor.track(options.toolCallId)
const result = await item.execute(args, {
sessionID: input.sessionID,
abort: abort.signal,
abort: options.abortSignal!,
messageID: assistantMsg.id,
callID: options.toolCallId,
metadata: async (val) => {
@@ -780,11 +825,10 @@ export namespace Session {
}
for (const [key, item] of Object.entries(await MCP.tools())) {
if (mode.tools[key] === false) continue
if (enabledTools[key] === false) continue
const execute = item.execute
if (!execute) continue
item.execute = async (args, opts) => {
await processor.track(opts.toolCallId)
const result = await execute(args, opts)
const output = result.content
.filter((x: any) => x.type === "text")
@@ -806,9 +850,9 @@ export namespace Session {
const params = {
temperature: model.info.temperature
? (mode.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID))
? (agent.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID))
: undefined,
topP: mode.topP ?? ProviderTransform.topP(input.providerID, input.modelID),
topP: agent.topP ?? ProviderTransform.topP(input.providerID, input.modelID),
}
await Plugin.trigger(
"chat.params",
@@ -859,7 +903,7 @@ export namespace Session {
},
modelID: input.modelID,
providerID: input.providerID,
mode: inputMode,
mode: inputAgent,
time: {
created: Date.now(),
},
@@ -871,8 +915,19 @@ export namespace Session {
messages,
}
},
async experimental_repairToolCall(input) {
return {
...input.toolCall,
input: JSON.stringify({
tool: input.toolCall.toolName,
error: input.error.message,
}),
toolName: "invalid",
}
},
maxRetries: 3,
maxOutputTokens: outputLimit,
activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
maxOutputTokens: model.info.id.startsWith("gpt-5") ? undefined : outputLimit,
abortSignal: abort.signal,
stopWhen: stepCountIs(1000),
providerOptions: {
@@ -920,15 +975,11 @@ export namespace Session {
}
function createProcessor(assistantMsg: MessageV2.Assistant, model: ModelsDev.Model) {
const toolCalls: Record<string, MessageV2.ToolPart> = {}
const snapshots: Record<string, string> = {}
const toolcalls: Record<string, MessageV2.ToolPart> = {}
let snapshot: string | undefined
return {
async track(toolCallID: string) {
const hash = await Snapshot.track()
if (hash) snapshots[toolCallID] = hash
},
partFromToolCall(toolCallID: string) {
return toolCalls[toolCallID]
return toolcalls[toolCallID]
},
async process(stream: StreamTextResult<Record<string, AITool>, never>) {
try {
@@ -944,7 +995,7 @@ export namespace Session {
case "tool-input-start":
const part = await updatePart({
id: toolCalls[value.id]?.id ?? Identifier.ascending("part"),
id: toolcalls[value.id]?.id ?? Identifier.ascending("part"),
messageID: assistantMsg.id,
sessionID: assistantMsg.sessionID,
type: "tool",
@@ -954,7 +1005,7 @@ export namespace Session {
status: "pending",
},
})
toolCalls[value.id] = part as MessageV2.ToolPart
toolcalls[value.id] = part as MessageV2.ToolPart
break
case "tool-input-delta":
@@ -964,10 +1015,11 @@ export namespace Session {
break
case "tool-call": {
const match = toolCalls[value.toolCallId]
const match = toolcalls[value.toolCallId]
if (match) {
const part = await updatePart({
...match,
tool: value.toolName,
state: {
status: "running",
input: value.input,
@@ -976,12 +1028,12 @@ export namespace Session {
},
},
})
toolCalls[value.toolCallId] = part as MessageV2.ToolPart
toolcalls[value.toolCallId] = part as MessageV2.ToolPart
}
break
}
case "tool-result": {
const match = toolCalls[value.toolCallId]
const match = toolcalls[value.toolCallId]
if (match && match.state.status === "running") {
await updatePart({
...match,
@@ -997,27 +1049,13 @@ export namespace Session {
},
},
})
delete toolCalls[value.toolCallId]
const snapshot = snapshots[value.toolCallId]
if (snapshot) {
const patch = await Snapshot.patch(snapshot)
if (patch.files.length) {
await updatePart({
id: Identifier.ascending("part"),
messageID: assistantMsg.id,
sessionID: assistantMsg.sessionID,
type: "patch",
hash: patch.hash,
files: patch.files,
})
}
}
delete toolcalls[value.toolCallId]
}
break
}
case "tool-error": {
const match = toolCalls[value.toolCallId]
const match = toolcalls[value.toolCallId]
if (match && match.state.status === "running") {
await updatePart({
...match,
@@ -1031,19 +1069,7 @@ export namespace Session {
},
},
})
delete toolCalls[value.toolCallId]
const snapshot = snapshots[value.toolCallId]
if (snapshot) {
const patch = await Snapshot.patch(snapshot)
await updatePart({
id: Identifier.ascending("part"),
messageID: assistantMsg.id,
sessionID: assistantMsg.sessionID,
type: "patch",
hash: patch.hash,
files: patch.files,
})
}
delete toolcalls[value.toolCallId]
}
break
}
@@ -1058,6 +1084,7 @@ export namespace Session {
sessionID: assistantMsg.sessionID,
type: "step-start",
})
snapshot = await Snapshot.track()
break
case "finish-step":
@@ -1073,6 +1100,20 @@ export namespace Session {
cost: usage.cost,
})
await updateMessage(assistantMsg)
if (snapshot) {
const patch = await Snapshot.patch(snapshot)
if (patch.files.length) {
await updatePart({
id: Identifier.ascending("part"),
messageID: assistantMsg.id,
sessionID: assistantMsg.sessionID,
type: "patch",
hash: patch.hash,
files: patch.files,
})
}
snapshot = undefined
}
break
case "text-start":
@@ -1320,9 +1361,19 @@ export namespace Session {
state().pending.set(sessionID, controller)
return {
signal: controller.signal,
[Symbol.dispose]() {
async [Symbol.dispose]() {
log.info("unlocking", { sessionID })
state().pending.delete(sessionID)
const isAutoCompacting = state().autoCompacting.get(sessionID) ?? false
if (isAutoCompacting) {
state().autoCompacting.delete(sessionID)
return
}
const session = await get(sessionID)
if (session.parentID) return
Bus.publish(Event.Idle, {
sessionID,
})
@@ -1345,10 +1396,10 @@ export namespace Session {
}
return {
cost: new Decimal(0)
.add(new Decimal(tokens.input).mul(model.cost.input).div(1_000_000))
.add(new Decimal(tokens.output).mul(model.cost.output).div(1_000_000))
.add(new Decimal(tokens.cache.read).mul(model.cost.cache_read ?? 0).div(1_000_000))
.add(new Decimal(tokens.cache.write).mul(model.cost.cache_write ?? 0).div(1_000_000))
.add(new Decimal(tokens.input).mul(model.cost?.input ?? 0).div(1_000_000))
.add(new Decimal(tokens.output).mul(model.cost?.output ?? 0).div(1_000_000))
.add(new Decimal(tokens.cache.read).mul(model.cost?.cache_read ?? 0).div(1_000_000))
.add(new Decimal(tokens.cache.write).mul(model.cost?.cache_write ?? 0).div(1_000_000))
.toNumber(),
tokens,
}
+25 -1
View File
@@ -172,6 +172,21 @@ export namespace MessageV2 {
})
export type FilePart = z.infer<typeof FilePart>
export const AgentPart = PartBase.extend({
type: z.literal("agent"),
name: z.string(),
source: z
.object({
value: z.string(),
start: z.number().int(),
end: z.number().int(),
})
.optional(),
}).openapi({
ref: "AgentPart",
})
export type AgentPart = z.infer<typeof AgentPart>
export const StepStartPart = PartBase.extend({
type: z.literal("step-start"),
}).openapi({
@@ -212,7 +227,16 @@ export namespace MessageV2 {
export type User = z.infer<typeof User>
export const Part = z
.discriminatedUnion("type", [TextPart, FilePart, ToolPart, StepStartPart, StepFinishPart, SnapshotPart, PatchPart])
.discriminatedUnion("type", [
TextPart,
FilePart,
ToolPart,
StepStartPart,
StepFinishPart,
SnapshotPart,
PatchPart,
AgentPart,
])
.openapi({
ref: "Part",
})
-74
View File
@@ -1,74 +0,0 @@
import { App } from "../app/app"
import { Config } from "../config/config"
import z from "zod"
import { Provider } from "../provider/provider"
export namespace Mode {
export const Info = z
.object({
name: z.string(),
temperature: z.number().optional(),
topP: z.number().optional(),
model: z
.object({
modelID: z.string(),
providerID: z.string(),
})
.optional(),
prompt: z.string().optional(),
tools: z.record(z.boolean()),
})
.openapi({
ref: "Mode",
})
export type Info = z.infer<typeof Info>
const state = App.state("mode", async () => {
const cfg = await Config.get()
const model = cfg.model ? Provider.parseModel(cfg.model) : undefined
const result: Record<string, Info> = {
build: {
model,
name: "build",
tools: {},
},
plan: {
name: "plan",
model,
tools: {
write: false,
edit: false,
patch: false,
},
},
}
for (const [key, value] of Object.entries(cfg.mode ?? {})) {
if (value.disable) continue
let item = result[key]
if (!item)
item = result[key] = {
name: key,
tools: {},
}
item.name = key
if (value.model) item.model = Provider.parseModel(value.model)
if (value.prompt) item.prompt = value.prompt
if (value.temperature != undefined) item.temperature = value.temperature
if (value.top_p != undefined) item.topP = value.top_p
if (value.tools)
item.tools = {
...value.tools,
...item.tools,
}
}
return result
})
export async function get(mode: string) {
return state().then((x) => x[mode])
}
export async function list() {
return state().then((x) => Object.values(x))
}
}
@@ -93,18 +93,6 @@ Carefully read the issue and think hard about a plan to solve it before coding.
- To test hypotheses, you can also add test statements or functions
- Revisit your assumptions if unexpected behavior occurs.
# How to create a Todo List
Use the following format to create a todo list:
```markdown
- [ ] Step 1: Description of the first step
- [ ] Step 2: Description of the second step
- [ ] Step 3: Description of the third step
```
Do not ever use HTML tags or any other formatting for the todo list, as it will not be rendered correctly. Always use the markdown format shown above. Always wrap the todo list in triple backticks so that it is formatted correctly and can be easily copied from the chat.
Always show the completed todo list to the user as the last item in your message, so that they can see that you have addressed all of the steps.
# Communication Guidelines
Always communicate clearly and concisely in a casual, friendly yet professional tone.
+13 -18
View File
@@ -60,33 +60,28 @@ export namespace SystemPrompt {
export async function custom() {
const { cwd, root } = App.info().path
const config = await Config.get()
const found = []
const paths = new Set<string>()
for (const item of CUSTOM_FILES) {
const matches = await Filesystem.findUp(item, cwd, root)
found.push(...matches.map((x) => Bun.file(x).text()))
matches.forEach((path) => paths.add(path))
}
found.push(
Bun.file(path.join(Global.Path.config, "AGENTS.md"))
.text()
.catch(() => ""),
)
found.push(
Bun.file(path.join(os.homedir(), ".claude", "CLAUDE.md"))
.text()
.catch(() => ""),
)
paths.add(path.join(Global.Path.config, "AGENTS.md"))
paths.add(path.join(os.homedir(), ".claude", "CLAUDE.md"))
if (config.instructions) {
for (const instruction of config.instructions) {
try {
const matches = await Filesystem.globUp(instruction, cwd, root)
found.push(...matches.map((x) => Bun.file(x).text()))
} catch {
continue // Skip invalid glob patterns
}
const matches = await Filesystem.globUp(instruction, cwd, root).catch(() => [])
matches.forEach((path) => paths.add(path))
}
}
const found = Array.from(paths).map((p) =>
Bun.file(p)
.text()
.catch(() => ""),
)
return Promise.all(found).then((result) => result.filter(Boolean))
}
+4 -1
View File
@@ -5,6 +5,7 @@ import fs from "fs/promises"
import { Log } from "../util/log"
import { Global } from "../global"
import { z } from "zod"
import { Config } from "../config/config"
export namespace Snapshot {
const log = Log.create({ service: "snapshot" })
@@ -26,6 +27,8 @@ export namespace Snapshot {
export async function track() {
const app = App.info()
if (!app.git) return
const cfg = await Config.get()
if (cfg.snapshot === false) return
const git = gitdir()
if (await fs.mkdir(git, { recursive: true })) {
await $`git init`
@@ -39,7 +42,7 @@ export namespace Snapshot {
log.info("initialized")
}
await $`git --git-dir ${git} add .`.quiet().cwd(app.path.cwd).nothrow()
const hash = await $`git --git-dir ${git} write-tree`.quiet().cwd(app.path.cwd).text()
const hash = await $`git --git-dir ${git} write-tree`.quiet().cwd(app.path.cwd).nothrow().text()
return hash.trim()
}
+30 -13
View File
@@ -1,4 +1,6 @@
import { z } from "zod"
import { exec } from "child_process"
import { text } from "stream/consumers"
import { Tool } from "./tool"
import DESCRIPTION from "./bash.txt"
import { App } from "../app/app"
@@ -75,9 +77,13 @@ export const BashTool = Tool.define("bash", {
if (["cd", "rm", "cp", "mv", "mkdir", "touch", "chmod", "chown"].includes(command[0])) {
for (const arg of command.slice(1)) {
if (arg.startsWith("-") || (command[0] === "chmod" && arg.startsWith("+"))) continue
const resolved = await $`realpath ${arg}`.text().then((x) => x.trim())
const resolved = await $`realpath ${arg}`
.quiet()
.nothrow()
.text()
.then((x) => x.trim())
log.info("resolved path", { arg, resolved })
if (!Filesystem.contains(app.path.cwd, resolved)) {
if (resolved && !Filesystem.contains(app.path.cwd, resolved)) {
throw new Error(
`This command references paths outside of ${app.path.cwd} so it is not allowed to be executed.`,
)
@@ -87,7 +93,7 @@ export const BashTool = Tool.define("bash", {
// always allow cd if it passes above check
if (!needsAsk && command[0] !== "cd") {
const ask = (() => {
const action = (() => {
for (const [pattern, value] of Object.entries(permissions)) {
const match = Wildcard.match(node.text, pattern)
log.info("checking", { text: node.text.trim(), pattern, match })
@@ -95,7 +101,12 @@ export const BashTool = Tool.define("bash", {
}
return "ask"
})()
if (ask === "ask") needsAsk = true
if (action === "deny") {
throw new Error(
"The user has specifically restricted access to this command, you are not allowed to execute it.",
)
}
if (action === "ask") needsAsk = true
}
}
@@ -112,18 +123,24 @@ export const BashTool = Tool.define("bash", {
})
}
const process = Bun.spawn({
cmd: ["bash", "-c", params.command],
const process = exec(params.command, {
cwd: app.path.cwd,
maxBuffer: MAX_OUTPUT_LENGTH,
signal: ctx.abort,
timeout: timeout,
stdout: "pipe",
stderr: "pipe",
maxBuffer: MAX_OUTPUT_LENGTH,
timeout,
})
await process.exited
const stdout = await new Response(process.stdout).text()
const stderr = await new Response(process.stderr).text()
const stdoutPromise = text(process.stdout!)
const stderrPromise = text(process.stderr!)
await new Promise<void>((resolve) => {
process.on("close", () => {
resolve()
})
})
const stdout = await stdoutPromise
const stderr = await stderrPromise
return {
title: params.command,
+17
View File
@@ -0,0 +1,17 @@
import { z } from "zod"
import { Tool } from "./tool"
export const InvalidTool = Tool.define("invalid", {
description: "Do not use",
parameters: z.object({
tool: z.string(),
error: z.string(),
}),
async execute(params) {
return {
title: "Invalid Tool",
output: `The arguments provided to the tool are invalid: ${params.error}`,
metadata: {},
}
},
})
+16 -19
View File
@@ -10,9 +10,12 @@ import { TaskTool } from "./task"
import { TodoWriteTool, TodoReadTool } from "./todo"
import { WebFetchTool } from "./webfetch"
import { WriteTool } from "./write"
import { InvalidTool } from "./invalid"
import { Config } from "../config/config"
export namespace ToolRegistry {
const ALL = [
InvalidTool,
BashTool,
EditTool,
WebFetchTool,
@@ -63,27 +66,21 @@ export namespace ToolRegistry {
return result
}
export function enabled(_providerID: string, modelID: string): Record<string, boolean> {
if (modelID.toLowerCase().includes("claude")) {
return {
patch: false,
}
export async function enabled(_providerID: string, _modelID: string): Promise<Record<string, boolean>> {
const cfg = await Config.get()
const result: Record<string, boolean> = {}
result["patch"] = false
if (cfg.permission?.edit === "deny") {
result["edit"] = false
result["patch"] = false
result["write"] = false
}
if (cfg?.permission?.bash === "deny") {
result["bash"] = false
}
if (
modelID.toLowerCase().includes("qwen") ||
modelID.includes("gpt-") ||
modelID.includes("o1") ||
modelID.includes("o3") ||
modelID.includes("codex")
) {
return {
patch: false,
todowrite: false,
todoread: false,
}
}
return {}
return result
}
function sanitizeGeminiParameters(schema: z.ZodTypeAny, visited = new Set()): z.ZodTypeAny {
+12 -5
View File
@@ -8,8 +8,13 @@ import { Identifier } from "../id/id"
import { Agent } from "../agent/agent"
export const TaskTool = Tool.define("task", async () => {
const agents = await Agent.list()
const description = DESCRIPTION.replace("{agents}", agents.map((a) => `- ${a.name}: ${a.description}`).join("\n"))
const agents = await Agent.list().then((x) => x.filter((a) => a.mode !== "primary"))
const description = DESCRIPTION.replace(
"{agents}",
agents
.map((a) => `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`)
.join("\n"),
)
return {
description,
parameters: z.object({
@@ -22,6 +27,7 @@ export const TaskTool = Tool.define("task", async () => {
const msg = await Session.getMessage(ctx.sessionID, ctx.messageID)
if (msg.info.role !== "assistant") throw new Error("Not an assistant message")
const agent = await Agent.get(params.subagent_type)
if (!agent) throw new Error(`Unknown agent type: ${params.subagent_type} is not a valid agent type`)
const messageID = Identifier.ascending("message")
const parts: Record<string, MessageV2.ToolPart> = {}
const unsub = Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
@@ -50,11 +56,12 @@ export const TaskTool = Tool.define("task", async () => {
sessionID: session.id,
modelID: model.modelID,
providerID: model.providerID,
mode: msg.info.mode,
system: agent.prompt,
agent: agent.name,
tools: {
...agent.tools,
todowrite: false,
todoread: false,
task: false,
...agent.tools,
},
parts: [
{
+2 -2
View File
@@ -5,8 +5,8 @@ import { App } from "../app/app"
const TodoInfo = z.object({
content: z.string().describe("Brief description of the task"),
status: z.enum(["pending", "in_progress", "completed", "cancelled"]).describe("Current status of the task"),
priority: z.enum(["high", "medium", "low"]).describe("Priority level of the task"),
status: z.string().describe("Current status of the task: pending, in_progress, completed, cancelled"),
priority: z.string().describe("Priority level of the task: high, medium, low"),
id: z.string().describe("Unique identifier for the todo item"),
})
type TodoInfo = z.infer<typeof TodoInfo>
+11 -47
View File
@@ -1,53 +1,17 @@
import { Global } from "../global"
import { Installation } from "../installation"
import path from "path"
import { NodeSDK } from "@opentelemetry/sdk-node"
import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
export namespace Trace {
export function init() {
if (!Installation.isDev()) return
const writer = Bun.file(path.join(Global.Path.data, "log", "fetch.log")).writer()
const sdk = new NodeSDK({
serviceName: "opencode",
instrumentations: [new FetchInstrumentation()],
traceExporter: new OTLPTraceExporter({
url: "http://localhost:4318/v1/traces", // or your OTLP endpoint
}),
})
const originalFetch = globalThis.fetch
// @ts-expect-error
globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url
const method = init?.method || "GET"
const urlObj = new URL(url)
writer.write(`\n${method} ${urlObj.pathname}${urlObj.search} HTTP/1.1\n`)
writer.write(`Host: ${urlObj.host}\n`)
if (init?.headers) {
if (init.headers instanceof Headers) {
init.headers.forEach((value, key) => {
writer.write(`${key}: ${value}\n`)
})
} else {
for (const [key, value] of Object.entries(init.headers)) {
writer.write(`${key}: ${value}\n`)
}
}
}
if (init?.body) {
writer.write(`\n${init.body}`)
}
writer.flush()
const response = await originalFetch(input, init)
const clonedResponse = response.clone()
writer.write(`\nHTTP/1.1 ${response.status} ${response.statusText}\n`)
response.headers.forEach((value, key) => {
writer.write(`${key}: ${value}\n`)
})
if (clonedResponse.body) {
clonedResponse.text().then(async (x) => {
writer.write(`\n${x}\n`)
})
}
writer.flush()
return response
}
sdk.start()
}
}
+9 -4
View File
@@ -1,21 +1,26 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/plugin",
"version": "0.3.113",
"version": "0.3.133",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit"
},
"exports": {
".": "./src/index.ts"
".": {
"development": "./src/index.ts",
"import": "./dist/index.js"
}
},
"files": [
"dist"
],
"dependencies": {
"@opencode-ai/sdk": "workspace:*"
},
"devDependencies": {
"typescript": "catalog:",
"@hey-api/openapi-ts": "0.80.1",
"@tsconfig/node22": "catalog:",
"@opencode-ai/sdk": "workspace:*"
"@tsconfig/node22": "catalog:"
}
}
+4 -1
View File
@@ -1,7 +1,10 @@
import { Plugin } from "./index"
export const ExamplePlugin: Plugin = async ({ app, client }) => {
export const ExamplePlugin: Plugin = async ({ app, client, $ }) => {
return {
permission: {},
async "chat.params"(input, output) {
output.topP = 1
},
}
}
+26 -45
View File
@@ -1,56 +1,37 @@
import type { Event, createOpencodeClient, App, Model, Provider, Permission, UserMessage, Part } from "@opencode-ai/sdk"
import { $ } from "bun"
import type { BunShell } from "./shell"
export type PluginInput = {
client: ReturnType<typeof createOpencodeClient>
app: App
$: $
$: BunShell
}
export type Plugin = (input: PluginInput) => Promise<Hooks>
export interface Hooks {
event?: (input: { event: Event }) => Promise<void>
chat?: {
/**
* Called when a new message is received
*/
message?: (input: {}, output: { message: UserMessage; parts: Part[] }) => Promise<void>
/**
* Modify parameters sent to LLM
*/
params?: (
input: { model: Model; provider: Provider; message: UserMessage },
output: { temperature: number; topP: number },
) => Promise<void>
}
permission?: {
/**
* Called when a permission is asked
*/
ask?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
}
tool?: {
execute?: {
/**
* Called before a tool is executed
*/
before?: (
input: { tool: string; sessionID: string; callID: string },
output: {
args: any
},
) => Promise<void>
/**
* Called after a tool is executed
*/
after?: (
input: { tool: string; sessionID: string; callID: string },
output: {
title: string
output: string
metadata: any
},
) => Promise<void>
}
}
/**
* Called when a new message is received
*/
"chat.message"?: (input: {}, output: { message: UserMessage; parts: Part[] }) => Promise<void>
/**
* Modify parameters sent to LLM
*/
"chat.params"?: (
input: { model: Model; provider: Provider; message: UserMessage },
output: { temperature: number; topP: number },
) => Promise<void>
"permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
"tool.execute.before"?: (
input: { tool: string; sessionID: string; callID: string },
output: { args: any },
) => Promise<void>
"tool.execute.after"?: (
input: { tool: string; sessionID: string; callID: string },
output: {
title: string
output: string
metadata: any
},
) => Promise<void>
}
+136
View File
@@ -0,0 +1,136 @@
export type ShellFunction = (input: Uint8Array) => Uint8Array
export type ShellExpression =
| { toString(): string }
| Array<ShellExpression>
| string
| { raw: string }
| ReadableStream
export interface BunShell {
(strings: TemplateStringsArray, ...expressions: ShellExpression[]): BunShellPromise
/**
* Perform bash-like brace expansion on the given pattern.
* @param pattern - Brace pattern to expand
*/
braces(pattern: string): string[]
/**
* Escape strings for input into shell commands.
*/
escape(input: string): string
/**
* Change the default environment variables for shells created by this instance.
*/
env(newEnv?: Record<string, string | undefined>): BunShell
/**
* Default working directory to use for shells created by this instance.
*/
cwd(newCwd?: string): BunShell
/**
* Configure the shell to not throw an exception on non-zero exit codes.
*/
nothrow(): BunShell
/**
* Configure whether or not the shell should throw an exception on non-zero exit codes.
*/
throws(shouldThrow: boolean): BunShell
}
export interface BunShellPromise extends Promise<BunShellOutput> {
readonly stdin: WritableStream
/**
* Change the current working directory of the shell.
*/
cwd(newCwd: string): this
/**
* Set environment variables for the shell.
*/
env(newEnv: Record<string, string> | undefined): this
/**
* By default, the shell will write to the current process's stdout and stderr, as well as buffering that output.
* This configures the shell to only buffer the output.
*/
quiet(): this
/**
* Read from stdout as a string, line by line
* Automatically calls quiet() to disable echoing to stdout.
*/
lines(): AsyncIterable<string>
/**
* Read from stdout as a string.
* Automatically calls quiet() to disable echoing to stdout.
*/
text(encoding?: BufferEncoding): Promise<string>
/**
* Read from stdout as a JSON object
* Automatically calls quiet()
*/
json(): Promise<any>
/**
* Read from stdout as an ArrayBuffer
* Automatically calls quiet()
*/
arrayBuffer(): Promise<ArrayBuffer>
/**
* Read from stdout as a Blob
* Automatically calls quiet()
*/
blob(): Promise<Blob>
/**
* Configure the shell to not throw an exception on non-zero exit codes.
*/
nothrow(): this
/**
* Configure whether or not the shell should throw an exception on non-zero exit codes.
*/
throws(shouldThrow: boolean): this
}
export interface BunShellOutput {
readonly stdout: Buffer
readonly stderr: Buffer
readonly exitCode: number
/**
* Read from stdout as a string
*/
text(encoding?: BufferEncoding): string
/**
* Read from stdout as a JSON object
*/
json(): any
/**
* Read from stdout as an ArrayBuffer
*/
arrayBuffer(): ArrayBuffer
/**
* Read from stdout as an Uint8Array
*/
bytes(): Uint8Array
/**
* Read from stdout as a Blob
*/
blob(): Blob
}
export type BunShellError = Error & BunShellOutput
+9
View File
@@ -0,0 +1,9 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/* deno-fmt-ignore-file */
/// <reference path="../../sst-env.d.ts" />
import "sst"
export {}
-88
View File
@@ -1,88 +0,0 @@
name: CI
on:
push:
branches-ignore:
- 'generated'
- 'codegen/**'
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
- 'stl-preview-base/**'
jobs:
lint:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/opencode-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Bootstrap
run: ./scripts/bootstrap
- name: Check types
run: ./scripts/lint
build:
timeout-minutes: 5
name: build
runs-on: ${{ github.repository == 'stainless-sdks/opencode-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Bootstrap
run: ./scripts/bootstrap
- name: Check build
run: ./scripts/build
- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/opencode-typescript'
id: github-oidc
uses: actions/github-script@v6
with:
script: core.setOutput('github_token', await core.getIDToken());
- name: Upload tarball
if: github.repository == 'stainless-sdks/opencode-typescript'
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
SHA: ${{ github.sha }}
run: ./scripts/utils/upload-artifact.sh
test:
timeout-minutes: 10
name: test
runs-on: ${{ github.repository == 'stainless-sdks/opencode-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Bootstrap
run: ./scripts/bootstrap
- name: Run tests
run: ./scripts/test
-32
View File
@@ -1,32 +0,0 @@
# This workflow is triggered when a GitHub release is created.
# It can also be run manually to re-publish to NPM in case it failed for some reason.
# You can run this workflow by navigating to https://www.github.com/sst/opencode-sdk-js/actions/workflows/publish-npm.yml
name: Publish NPM
on:
workflow_dispatch:
release:
types: [published]
jobs:
publish:
name: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: |
yarn install
- name: Publish to NPM
run: |
bash ./bin/publish-npm
env:
NPM_TOKEN: ${{ secrets.OPENCODE_NPM_TOKEN || secrets.NPM_TOKEN }}
-21
View File
@@ -1,21 +0,0 @@
name: Release Doctor
on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
release_doctor:
name: release doctor
runs-on: ubuntu-latest
if: github.repository == 'sst/opencode-sdk-js' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
steps:
- uses: actions/checkout@v4
- name: Check release environment
run: |
bash ./bin/check-release-environment
env:
NPM_TOKEN: ${{ secrets.OPENCODE_NPM_TOKEN || secrets.NPM_TOKEN }}
+3 -3
View File
@@ -1,4 +1,4 @@
configured_endpoints: 34
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-2ebd9d5478864042a2e01b4995f42acbc39069fa7fcccd1c2e567366ee6c243d.yml
openapi_spec_hash: 2a34451b288ea30af1cb61332c417c2a
config_hash: 11a6f0803eb407367c3f677d3e524c37
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-da1c340135c3dd6b1edb4e00e7039d2ac54d59271683a8b6ed528e51137ce41a.yml
openapi_spec_hash: 0cdd9b6273d72f5a6f484a2999ff0632
config_hash: 7581d5948150d4ef7dd7b13d0845dbeb
+4 -3
View File
@@ -18,18 +18,18 @@ Methods:
Response Types:
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Agent">Agent</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#App">App</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Mode">Mode</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Model">Model</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Provider">Provider</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppProvidersResponse">AppProvidersResponse</a>
Methods:
- <code title="get /agent">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Agents">Agents</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Agent">Agent</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /app">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#App">App</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /app/init">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /log">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Log">Log</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppLogParams">AppLogParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /mode">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Modes">Modes</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Mode">Mode</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /config/providers">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Providers">Providers</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppProvidersResponse">AppProvidersResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
# Find
@@ -65,7 +65,6 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#KeybindsConfig">KeybindsConfig</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#McpLocalConfig">McpLocalConfig</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#McpRemoteConfig">McpRemoteConfig</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ModeConfig">ModeConfig</a>
Methods:
@@ -75,6 +74,7 @@ Methods:
Params Types:
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AgentPartInputParam">AgentPartInputParam</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartInputParam">FilePartInputParam</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSourceUnionParam">FilePartSourceUnionParam</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSourceTextParam">FilePartSourceTextParam</a>
@@ -84,6 +84,7 @@ Params Types:
Response Types:
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AgentPart">AgentPart</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePart">FilePart</a>
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSource">FilePartSource</a>
+80 -58
View File
@@ -31,6 +31,14 @@ func NewAppService(opts ...option.RequestOption) (r *AppService) {
return
}
// List all agents
func (r *AppService) Agents(ctx context.Context, opts ...option.RequestOption) (res *[]Agent, err error) {
opts = append(r.Options[:], opts...)
path := "agent"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}
// Get app info
func (r *AppService) Get(ctx context.Context, opts ...option.RequestOption) (res *App, err error) {
opts = append(r.Options[:], opts...)
@@ -55,14 +63,6 @@ func (r *AppService) Log(ctx context.Context, body AppLogParams, opts ...option.
return
}
// List all modes
func (r *AppService) Modes(ctx context.Context, opts ...option.RequestOption) (res *[]Mode, err error) {
opts = append(r.Options[:], opts...)
path := "mode"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}
// List all providers
func (r *AppService) Providers(ctx context.Context, opts ...option.RequestOption) (res *AppProvidersResponse, err error) {
opts = append(r.Options[:], opts...)
@@ -71,6 +71,78 @@ func (r *AppService) Providers(ctx context.Context, opts ...option.RequestOption
return
}
type Agent struct {
Mode AgentMode `json:"mode,required"`
Name string `json:"name,required"`
Tools map[string]bool `json:"tools,required"`
Description string `json:"description"`
Model AgentModel `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"topP"`
JSON agentJSON `json:"-"`
}
// agentJSON contains the JSON metadata for the struct [Agent]
type agentJSON struct {
Mode apijson.Field
Name apijson.Field
Tools apijson.Field
Description apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *Agent) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r agentJSON) RawJSON() string {
return r.raw
}
type AgentMode string
const (
AgentModeSubagent AgentMode = "subagent"
AgentModePrimary AgentMode = "primary"
AgentModeAll AgentMode = "all"
)
func (r AgentMode) IsKnown() bool {
switch r {
case AgentModeSubagent, AgentModePrimary, AgentModeAll:
return true
}
return false
}
type AgentModel struct {
ModelID string `json:"modelID,required"`
ProviderID string `json:"providerID,required"`
JSON agentModelJSON `json:"-"`
}
// agentModelJSON contains the JSON metadata for the struct [AgentModel]
type agentModelJSON struct {
ModelID apijson.Field
ProviderID apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *AgentModel) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r agentModelJSON) RawJSON() string {
return r.raw
}
type App struct {
Git bool `json:"git,required"`
Hostname string `json:"hostname,required"`
@@ -145,56 +217,6 @@ func (r appTimeJSON) RawJSON() string {
return r.raw
}
type Mode struct {
Name string `json:"name,required"`
Tools map[string]bool `json:"tools,required"`
Model ModeModel `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
JSON modeJSON `json:"-"`
}
// modeJSON contains the JSON metadata for the struct [Mode]
type modeJSON struct {
Name apijson.Field
Tools apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *Mode) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r modeJSON) RawJSON() string {
return r.raw
}
type ModeModel struct {
ModelID string `json:"modelID,required"`
ProviderID string `json:"providerID,required"`
JSON modeModelJSON `json:"-"`
}
// modeModelJSON contains the JSON metadata for the struct [ModeModel]
type modeModelJSON struct {
ModelID apijson.Field
ProviderID apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ModeModel) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r modeModelJSON) RawJSON() string {
return r.raw
}
type Model struct {
ID string `json:"id,required"`
Attachment bool `json:"attachment,required"`
+22 -22
View File
@@ -13,6 +13,28 @@ import (
"github.com/sst/opencode-sdk-go/option"
)
func TestAppAgents(t *testing.T) {
t.Skip("skipped: tests are disabled for the time being")
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
baseURL = envURL
}
if !testutil.CheckTestServer(t, baseURL) {
return
}
client := opencode.NewClient(
option.WithBaseURL(baseURL),
)
_, err := client.App.Agents(context.TODO())
if err != nil {
var apierr *opencode.Error
if errors.As(err, &apierr) {
t.Log(string(apierr.DumpRequest(true)))
}
t.Fatalf("err should be nil: %s", err.Error())
}
}
func TestAppGet(t *testing.T) {
t.Skip("skipped: tests are disabled for the time being")
baseURL := "http://localhost:4010"
@@ -86,28 +108,6 @@ func TestAppLogWithOptionalParams(t *testing.T) {
}
}
func TestAppModes(t *testing.T) {
t.Skip("skipped: tests are disabled for the time being")
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
baseURL = envURL
}
if !testutil.CheckTestServer(t, baseURL) {
return
}
client := opencode.NewClient(
option.WithBaseURL(baseURL),
)
_, err := client.App.Modes(context.TODO())
if err != nil {
var apierr *opencode.Error
if errors.As(err, &apierr) {
t.Log(string(apierr.DumpRequest(true)))
}
t.Fatalf("err should be nil: %s", err.Error())
}
}
func TestAppProviders(t *testing.T) {
t.Skip("skipped: tests are disabled for the time being")
baseURL := "http://localhost:4010"
+431 -46
View File
@@ -43,7 +43,7 @@ func (r *ConfigService) Get(ctx context.Context, opts ...option.RequestOption) (
type Config struct {
// JSON schema reference for configuration validation
Schema string `json:"$schema"`
// Modes configuration, see https://opencode.ai/docs/modes
// Agent configuration, see https://opencode.ai/docs/agent
Agent ConfigAgent `json:"agent"`
// @deprecated Use 'share' field instead. Share newly created sessions
// automatically
@@ -51,27 +51,30 @@ type Config struct {
// Automatically update to the latest version
Autoupdate bool `json:"autoupdate"`
// Disable providers that are loaded automatically
DisabledProviders []string `json:"disabled_providers"`
Experimental ConfigExperimental `json:"experimental"`
DisabledProviders []string `json:"disabled_providers"`
Experimental ConfigExperimental `json:"experimental"`
Formatter map[string]ConfigFormatter `json:"formatter"`
// Additional instruction files or patterns to include
Instructions []string `json:"instructions"`
// Custom keybind configurations
Keybinds KeybindsConfig `json:"keybinds"`
// @deprecated Always uses stretch layout.
Layout ConfigLayout `json:"layout"`
Layout ConfigLayout `json:"layout"`
Lsp map[string]ConfigLsp `json:"lsp"`
// MCP (Model Context Protocol) server configurations
Mcp map[string]ConfigMcp `json:"mcp"`
// Modes configuration, see https://opencode.ai/docs/modes
// @deprecated Use `agent` field instead.
Mode ConfigMode `json:"mode"`
// Model to use in the format of provider/model, eg anthropic/claude-2
Model string `json:"model"`
Permission ConfigPermission `json:"permission"`
Plugin []string `json:"plugin"`
// Custom provider configurations and model overrides
Provider map[string]ConfigProvider `json:"provider"`
// Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
// enables automatic sharing, 'disabled' disables all sharing
Share ConfigShare `json:"share"`
// Small model to use for tasks like summarization and title generation in the
// Small model to use for tasks like title generation in the
// format of provider/model
SmallModel string `json:"small_model"`
// Theme name to use for the interface
@@ -89,13 +92,16 @@ type configJSON struct {
Autoupdate apijson.Field
DisabledProviders apijson.Field
Experimental apijson.Field
Formatter apijson.Field
Instructions apijson.Field
Keybinds apijson.Field
Layout apijson.Field
Lsp apijson.Field
Mcp apijson.Field
Mode apijson.Field
Model apijson.Field
Permission apijson.Field
Plugin apijson.Field
Provider apijson.Field
Share apijson.Field
SmallModel apijson.Field
@@ -113,16 +119,20 @@ func (r configJSON) RawJSON() string {
return r.raw
}
// Modes configuration, see https://opencode.ai/docs/modes
// Agent configuration, see https://opencode.ai/docs/agent
type ConfigAgent struct {
Build ConfigAgentBuild `json:"build"`
General ConfigAgentGeneral `json:"general"`
Plan ConfigAgentPlan `json:"plan"`
ExtraFields map[string]ConfigAgent `json:"-,extras"`
JSON configAgentJSON `json:"-"`
}
// configAgentJSON contains the JSON metadata for the struct [ConfigAgent]
type configAgentJSON struct {
Build apijson.Field
General apijson.Field
Plan apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
@@ -135,16 +145,82 @@ func (r configAgentJSON) RawJSON() string {
return r.raw
}
type ConfigAgentBuild struct {
// Description of when to use the agent
Description string `json:"description"`
Disable bool `json:"disable"`
Mode ConfigAgentBuildMode `json:"mode"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
TopP float64 `json:"top_p"`
JSON configAgentBuildJSON `json:"-"`
}
// configAgentBuildJSON contains the JSON metadata for the struct
// [ConfigAgentBuild]
type configAgentBuildJSON struct {
Description apijson.Field
Disable apijson.Field
Mode apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigAgentBuild) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configAgentBuildJSON) RawJSON() string {
return r.raw
}
type ConfigAgentBuildMode string
const (
ConfigAgentBuildModeSubagent ConfigAgentBuildMode = "subagent"
ConfigAgentBuildModePrimary ConfigAgentBuildMode = "primary"
ConfigAgentBuildModeAll ConfigAgentBuildMode = "all"
)
func (r ConfigAgentBuildMode) IsKnown() bool {
switch r {
case ConfigAgentBuildModeSubagent, ConfigAgentBuildModePrimary, ConfigAgentBuildModeAll:
return true
}
return false
}
type ConfigAgentGeneral struct {
Description string `json:"description,required"`
// Description of when to use the agent
Description string `json:"description"`
Disable bool `json:"disable"`
Mode ConfigAgentGeneralMode `json:"mode"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
TopP float64 `json:"top_p"`
JSON configAgentGeneralJSON `json:"-"`
ModeConfig
}
// configAgentGeneralJSON contains the JSON metadata for the struct
// [ConfigAgentGeneral]
type configAgentGeneralJSON struct {
Description apijson.Field
Disable apijson.Field
Mode apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
@@ -157,6 +233,73 @@ func (r configAgentGeneralJSON) RawJSON() string {
return r.raw
}
type ConfigAgentGeneralMode string
const (
ConfigAgentGeneralModeSubagent ConfigAgentGeneralMode = "subagent"
ConfigAgentGeneralModePrimary ConfigAgentGeneralMode = "primary"
ConfigAgentGeneralModeAll ConfigAgentGeneralMode = "all"
)
func (r ConfigAgentGeneralMode) IsKnown() bool {
switch r {
case ConfigAgentGeneralModeSubagent, ConfigAgentGeneralModePrimary, ConfigAgentGeneralModeAll:
return true
}
return false
}
type ConfigAgentPlan struct {
// Description of when to use the agent
Description string `json:"description"`
Disable bool `json:"disable"`
Mode ConfigAgentPlanMode `json:"mode"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
TopP float64 `json:"top_p"`
JSON configAgentPlanJSON `json:"-"`
}
// configAgentPlanJSON contains the JSON metadata for the struct [ConfigAgentPlan]
type configAgentPlanJSON struct {
Description apijson.Field
Disable apijson.Field
Mode apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigAgentPlan) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configAgentPlanJSON) RawJSON() string {
return r.raw
}
type ConfigAgentPlanMode string
const (
ConfigAgentPlanModeSubagent ConfigAgentPlanMode = "subagent"
ConfigAgentPlanModePrimary ConfigAgentPlanMode = "primary"
ConfigAgentPlanModeAll ConfigAgentPlanMode = "all"
)
func (r ConfigAgentPlanMode) IsKnown() bool {
switch r {
case ConfigAgentPlanModeSubagent, ConfigAgentPlanModePrimary, ConfigAgentPlanModeAll:
return true
}
return false
}
type ConfigExperimental struct {
Hook ConfigExperimentalHook `json:"hook"`
JSON configExperimentalJSON `json:"-"`
@@ -247,6 +390,32 @@ func (r configExperimentalHookSessionCompletedJSON) RawJSON() string {
return r.raw
}
type ConfigFormatter struct {
Command []string `json:"command"`
Disabled bool `json:"disabled"`
Environment map[string]string `json:"environment"`
Extensions []string `json:"extensions"`
JSON configFormatterJSON `json:"-"`
}
// configFormatterJSON contains the JSON metadata for the struct [ConfigFormatter]
type configFormatterJSON struct {
Command apijson.Field
Disabled apijson.Field
Environment apijson.Field
Extensions apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigFormatter) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configFormatterJSON) RawJSON() string {
return r.raw
}
// @deprecated Always uses stretch layout.
type ConfigLayout string
@@ -263,6 +432,139 @@ func (r ConfigLayout) IsKnown() bool {
return false
}
type ConfigLsp struct {
// This field can have the runtime type of [[]string].
Command interface{} `json:"command"`
Disabled bool `json:"disabled"`
// This field can have the runtime type of [map[string]string].
Env interface{} `json:"env"`
// This field can have the runtime type of [[]string].
Extensions interface{} `json:"extensions"`
// This field can have the runtime type of [map[string]interface{}].
Initialization interface{} `json:"initialization"`
JSON configLspJSON `json:"-"`
union ConfigLspUnion
}
// configLspJSON contains the JSON metadata for the struct [ConfigLsp]
type configLspJSON struct {
Command apijson.Field
Disabled apijson.Field
Env apijson.Field
Extensions apijson.Field
Initialization apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r configLspJSON) RawJSON() string {
return r.raw
}
func (r *ConfigLsp) UnmarshalJSON(data []byte) (err error) {
*r = ConfigLsp{}
err = apijson.UnmarshalRoot(data, &r.union)
if err != nil {
return err
}
return apijson.Port(r.union, &r)
}
// AsUnion returns a [ConfigLspUnion] interface which you can cast to the specific
// types for more type safety.
//
// Possible runtime types of the union are [ConfigLspDisabled], [ConfigLspObject].
func (r ConfigLsp) AsUnion() ConfigLspUnion {
return r.union
}
// Union satisfied by [ConfigLspDisabled] or [ConfigLspObject].
type ConfigLspUnion interface {
implementsConfigLsp()
}
func init() {
apijson.RegisterUnion(
reflect.TypeOf((*ConfigLspUnion)(nil)).Elem(),
"",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(ConfigLspDisabled{}),
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(ConfigLspObject{}),
},
)
}
type ConfigLspDisabled struct {
Disabled ConfigLspDisabledDisabled `json:"disabled,required"`
JSON configLspDisabledJSON `json:"-"`
}
// configLspDisabledJSON contains the JSON metadata for the struct
// [ConfigLspDisabled]
type configLspDisabledJSON struct {
Disabled apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigLspDisabled) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configLspDisabledJSON) RawJSON() string {
return r.raw
}
func (r ConfigLspDisabled) implementsConfigLsp() {}
type ConfigLspDisabledDisabled bool
const (
ConfigLspDisabledDisabledTrue ConfigLspDisabledDisabled = true
)
func (r ConfigLspDisabledDisabled) IsKnown() bool {
switch r {
case ConfigLspDisabledDisabledTrue:
return true
}
return false
}
type ConfigLspObject struct {
Command []string `json:"command,required"`
Disabled bool `json:"disabled"`
Env map[string]string `json:"env"`
Extensions []string `json:"extensions"`
Initialization map[string]interface{} `json:"initialization"`
JSON configLspObjectJSON `json:"-"`
}
// configLspObjectJSON contains the JSON metadata for the struct [ConfigLspObject]
type configLspObjectJSON struct {
Command apijson.Field
Disabled apijson.Field
Env apijson.Field
Extensions apijson.Field
Initialization apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigLspObject) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configLspObjectJSON) RawJSON() string {
return r.raw
}
func (r ConfigLspObject) implementsConfigLsp() {}
type ConfigMcp struct {
// Type of MCP server connection
Type ConfigMcpType `json:"type,required"`
@@ -351,11 +653,11 @@ func (r ConfigMcpType) IsKnown() bool {
return false
}
// Modes configuration, see https://opencode.ai/docs/modes
// @deprecated Use `agent` field instead.
type ConfigMode struct {
Build ModeConfig `json:"build"`
Plan ModeConfig `json:"plan"`
ExtraFields map[string]ModeConfig `json:"-,extras"`
Build ConfigModeBuild `json:"build"`
Plan ConfigModePlan `json:"plan"`
ExtraFields map[string]ConfigMode `json:"-,extras"`
JSON configModeJSON `json:"-"`
}
@@ -375,6 +677,108 @@ func (r configModeJSON) RawJSON() string {
return r.raw
}
type ConfigModeBuild struct {
// Description of when to use the agent
Description string `json:"description"`
Disable bool `json:"disable"`
Mode ConfigModeBuildMode `json:"mode"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
TopP float64 `json:"top_p"`
JSON configModeBuildJSON `json:"-"`
}
// configModeBuildJSON contains the JSON metadata for the struct [ConfigModeBuild]
type configModeBuildJSON struct {
Description apijson.Field
Disable apijson.Field
Mode apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigModeBuild) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configModeBuildJSON) RawJSON() string {
return r.raw
}
type ConfigModeBuildMode string
const (
ConfigModeBuildModeSubagent ConfigModeBuildMode = "subagent"
ConfigModeBuildModePrimary ConfigModeBuildMode = "primary"
ConfigModeBuildModeAll ConfigModeBuildMode = "all"
)
func (r ConfigModeBuildMode) IsKnown() bool {
switch r {
case ConfigModeBuildModeSubagent, ConfigModeBuildModePrimary, ConfigModeBuildModeAll:
return true
}
return false
}
type ConfigModePlan struct {
// Description of when to use the agent
Description string `json:"description"`
Disable bool `json:"disable"`
Mode ConfigModePlanMode `json:"mode"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
TopP float64 `json:"top_p"`
JSON configModePlanJSON `json:"-"`
}
// configModePlanJSON contains the JSON metadata for the struct [ConfigModePlan]
type configModePlanJSON struct {
Description apijson.Field
Disable apijson.Field
Mode apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
TopP apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ConfigModePlan) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r configModePlanJSON) RawJSON() string {
return r.raw
}
type ConfigModePlanMode string
const (
ConfigModePlanModeSubagent ConfigModePlanMode = "subagent"
ConfigModePlanModePrimary ConfigModePlanMode = "primary"
ConfigModePlanModeAll ConfigModePlanMode = "all"
)
func (r ConfigModePlanMode) IsKnown() bool {
switch r {
case ConfigModePlanModeSubagent, ConfigModePlanModePrimary, ConfigModePlanModeAll:
return true
}
return false
}
type ConfigPermission struct {
Bash ConfigPermissionBashUnion `json:"bash"`
Edit ConfigPermissionEdit `json:"edit"`
@@ -423,11 +827,12 @@ type ConfigPermissionBashString string
const (
ConfigPermissionBashStringAsk ConfigPermissionBashString = "ask"
ConfigPermissionBashStringAllow ConfigPermissionBashString = "allow"
ConfigPermissionBashStringDeny ConfigPermissionBashString = "deny"
)
func (r ConfigPermissionBashString) IsKnown() bool {
switch r {
case ConfigPermissionBashStringAsk, ConfigPermissionBashStringAllow:
case ConfigPermissionBashStringAsk, ConfigPermissionBashStringAllow, ConfigPermissionBashStringDeny:
return true
}
return false
@@ -444,11 +849,12 @@ type ConfigPermissionBashMapItem string
const (
ConfigPermissionBashMapAsk ConfigPermissionBashMapItem = "ask"
ConfigPermissionBashMapAllow ConfigPermissionBashMapItem = "allow"
ConfigPermissionBashMapDeny ConfigPermissionBashMapItem = "deny"
)
func (r ConfigPermissionBashMapItem) IsKnown() bool {
switch r {
case ConfigPermissionBashMapAsk, ConfigPermissionBashMapAllow:
case ConfigPermissionBashMapAsk, ConfigPermissionBashMapAllow, ConfigPermissionBashMapDeny:
return true
}
return false
@@ -459,11 +865,12 @@ type ConfigPermissionEdit string
const (
ConfigPermissionEditAsk ConfigPermissionEdit = "ask"
ConfigPermissionEditAllow ConfigPermissionEdit = "allow"
ConfigPermissionEditDeny ConfigPermissionEdit = "deny"
)
func (r ConfigPermissionEdit) IsKnown() bool {
switch r {
case ConfigPermissionEditAsk, ConfigPermissionEditAllow:
case ConfigPermissionEditAsk, ConfigPermissionEditAllow, ConfigPermissionEditDeny:
return true
}
return false
@@ -701,9 +1108,13 @@ type KeybindsConfig struct {
SessionShare string `json:"session_share,required"`
// Unshare current session
SessionUnshare string `json:"session_unshare,required"`
// Next mode
// Next agent
SwitchAgent string `json:"switch_agent,required"`
// Previous agent
SwitchAgentReverse string `json:"switch_agent_reverse,required"`
// @deprecated use switch_agent. Next mode
SwitchMode string `json:"switch_mode,required"`
// Previous Mode
// @deprecated use switch_agent_reverse. Previous mode
SwitchModeReverse string `json:"switch_mode_reverse,required"`
// List available themes
ThemeList string `json:"theme_list,required"`
@@ -748,6 +1159,8 @@ type keybindsConfigJSON struct {
SessionNew apijson.Field
SessionShare apijson.Field
SessionUnshare apijson.Field
SwitchAgent apijson.Field
SwitchAgentReverse apijson.Field
SwitchMode apijson.Field
SwitchModeReverse apijson.Field
ThemeList apijson.Field
@@ -857,31 +1270,3 @@ func (r McpRemoteConfigType) IsKnown() bool {
}
return false
}
type ModeConfig struct {
Disable bool `json:"disable"`
Model string `json:"model"`
Prompt string `json:"prompt"`
Temperature float64 `json:"temperature"`
Tools map[string]bool `json:"tools"`
JSON modeConfigJSON `json:"-"`
}
// modeConfigJSON contains the JSON metadata for the struct [ModeConfig]
type modeConfigJSON struct {
Disable apijson.Field
Model apijson.Field
Prompt apijson.Field
Temperature apijson.Field
Tools apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *ModeConfig) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r modeConfigJSON) RawJSON() string {
return r.raw
}
+123 -121
View File
@@ -54,13 +54,13 @@ type EventListResponse struct {
// [EventListResponseEventMessageRemovedProperties],
// [EventListResponseEventMessagePartUpdatedProperties],
// [EventListResponseEventMessagePartRemovedProperties],
// [EventListResponseEventStorageWriteProperties], [Permission],
// [EventListResponseEventStorageWriteProperties],
// [EventListResponseEventFileEditedProperties], [interface{}], [Permission],
// [EventListResponseEventPermissionRepliedProperties],
// [EventListResponseEventFileEditedProperties],
// [EventListResponseEventSessionUpdatedProperties],
// [EventListResponseEventSessionDeletedProperties],
// [EventListResponseEventSessionIdleProperties],
// [EventListResponseEventSessionErrorProperties], [interface{}],
// [EventListResponseEventSessionErrorProperties],
// [EventListResponseEventFileWatcherUpdatedProperties],
// [EventListResponseEventIdeInstalledProperties].
Properties interface{} `json:"properties,required"`
@@ -100,11 +100,12 @@ func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) {
// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
// [EventListResponseEventMessagePartUpdated],
// [EventListResponseEventMessagePartRemoved],
// [EventListResponseEventStorageWrite], [EventListResponseEventPermissionUpdated],
// [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
// [EventListResponseEventStorageWrite], [EventListResponseEventFileEdited],
// [EventListResponseEventServerConnected],
// [EventListResponseEventPermissionUpdated],
// [EventListResponseEventPermissionReplied],
// [EventListResponseEventSessionUpdated], [EventListResponseEventSessionDeleted],
// [EventListResponseEventSessionIdle], [EventListResponseEventSessionError],
// [EventListResponseEventServerConnected],
// [EventListResponseEventFileWatcherUpdated],
// [EventListResponseEventIdeInstalled].
func (r EventListResponse) AsUnion() EventListResponseUnion {
@@ -116,11 +117,12 @@ func (r EventListResponse) AsUnion() EventListResponseUnion {
// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
// [EventListResponseEventMessagePartUpdated],
// [EventListResponseEventMessagePartRemoved],
// [EventListResponseEventStorageWrite], [EventListResponseEventPermissionUpdated],
// [EventListResponseEventPermissionReplied], [EventListResponseEventFileEdited],
// [EventListResponseEventStorageWrite], [EventListResponseEventFileEdited],
// [EventListResponseEventServerConnected],
// [EventListResponseEventPermissionUpdated],
// [EventListResponseEventPermissionReplied],
// [EventListResponseEventSessionUpdated], [EventListResponseEventSessionDeleted],
// [EventListResponseEventSessionIdle], [EventListResponseEventSessionError],
// [EventListResponseEventServerConnected],
// [EventListResponseEventFileWatcherUpdated] or
// [EventListResponseEventIdeInstalled].
type EventListResponseUnion interface {
@@ -166,6 +168,16 @@ func init() {
Type: reflect.TypeOf(EventListResponseEventStorageWrite{}),
DiscriminatorValue: "storage.write",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventFileEdited{}),
DiscriminatorValue: "file.edited",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventServerConnected{}),
DiscriminatorValue: "server.connected",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventPermissionUpdated{}),
@@ -176,11 +188,6 @@ func init() {
Type: reflect.TypeOf(EventListResponseEventPermissionReplied{}),
DiscriminatorValue: "permission.replied",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventFileEdited{}),
DiscriminatorValue: "file.edited",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventSessionUpdated{}),
@@ -201,11 +208,6 @@ func init() {
Type: reflect.TypeOf(EventListResponseEventSessionError{}),
DiscriminatorValue: "session.error",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventServerConnected{}),
DiscriminatorValue: "server.connected",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}),
@@ -649,6 +651,105 @@ func (r EventListResponseEventStorageWriteType) IsKnown() bool {
return false
}
type EventListResponseEventFileEdited struct {
Properties EventListResponseEventFileEditedProperties `json:"properties,required"`
Type EventListResponseEventFileEditedType `json:"type,required"`
JSON eventListResponseEventFileEditedJSON `json:"-"`
}
// eventListResponseEventFileEditedJSON contains the JSON metadata for the struct
// [EventListResponseEventFileEdited]
type eventListResponseEventFileEditedJSON struct {
Properties apijson.Field
Type apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventFileEdited) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventFileEditedJSON) RawJSON() string {
return r.raw
}
func (r EventListResponseEventFileEdited) implementsEventListResponse() {}
type EventListResponseEventFileEditedProperties struct {
File string `json:"file,required"`
JSON eventListResponseEventFileEditedPropertiesJSON `json:"-"`
}
// eventListResponseEventFileEditedPropertiesJSON contains the JSON metadata for
// the struct [EventListResponseEventFileEditedProperties]
type eventListResponseEventFileEditedPropertiesJSON struct {
File apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventFileEditedProperties) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventFileEditedPropertiesJSON) RawJSON() string {
return r.raw
}
type EventListResponseEventFileEditedType string
const (
EventListResponseEventFileEditedTypeFileEdited EventListResponseEventFileEditedType = "file.edited"
)
func (r EventListResponseEventFileEditedType) IsKnown() bool {
switch r {
case EventListResponseEventFileEditedTypeFileEdited:
return true
}
return false
}
type EventListResponseEventServerConnected struct {
Properties interface{} `json:"properties,required"`
Type EventListResponseEventServerConnectedType `json:"type,required"`
JSON eventListResponseEventServerConnectedJSON `json:"-"`
}
// eventListResponseEventServerConnectedJSON contains the JSON metadata for the
// struct [EventListResponseEventServerConnected]
type eventListResponseEventServerConnectedJSON struct {
Properties apijson.Field
Type apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventServerConnected) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventServerConnectedJSON) RawJSON() string {
return r.raw
}
func (r EventListResponseEventServerConnected) implementsEventListResponse() {}
type EventListResponseEventServerConnectedType string
const (
EventListResponseEventServerConnectedTypeServerConnected EventListResponseEventServerConnectedType = "server.connected"
)
func (r EventListResponseEventServerConnectedType) IsKnown() bool {
switch r {
case EventListResponseEventServerConnectedTypeServerConnected:
return true
}
return false
}
type EventListResponseEventPermissionUpdated struct {
Properties Permission `json:"properties,required"`
Type EventListResponseEventPermissionUpdatedType `json:"type,required"`
@@ -752,66 +853,6 @@ func (r EventListResponseEventPermissionRepliedType) IsKnown() bool {
return false
}
type EventListResponseEventFileEdited struct {
Properties EventListResponseEventFileEditedProperties `json:"properties,required"`
Type EventListResponseEventFileEditedType `json:"type,required"`
JSON eventListResponseEventFileEditedJSON `json:"-"`
}
// eventListResponseEventFileEditedJSON contains the JSON metadata for the struct
// [EventListResponseEventFileEdited]
type eventListResponseEventFileEditedJSON struct {
Properties apijson.Field
Type apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventFileEdited) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventFileEditedJSON) RawJSON() string {
return r.raw
}
func (r EventListResponseEventFileEdited) implementsEventListResponse() {}
type EventListResponseEventFileEditedProperties struct {
File string `json:"file,required"`
JSON eventListResponseEventFileEditedPropertiesJSON `json:"-"`
}
// eventListResponseEventFileEditedPropertiesJSON contains the JSON metadata for
// the struct [EventListResponseEventFileEditedProperties]
type eventListResponseEventFileEditedPropertiesJSON struct {
File apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventFileEditedProperties) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventFileEditedPropertiesJSON) RawJSON() string {
return r.raw
}
type EventListResponseEventFileEditedType string
const (
EventListResponseEventFileEditedTypeFileEdited EventListResponseEventFileEditedType = "file.edited"
)
func (r EventListResponseEventFileEditedType) IsKnown() bool {
switch r {
case EventListResponseEventFileEditedTypeFileEdited:
return true
}
return false
}
type EventListResponseEventSessionUpdated struct {
Properties EventListResponseEventSessionUpdatedProperties `json:"properties,required"`
Type EventListResponseEventSessionUpdatedType `json:"type,required"`
@@ -1188,45 +1229,6 @@ func (r EventListResponseEventSessionErrorType) IsKnown() bool {
return false
}
type EventListResponseEventServerConnected struct {
Properties interface{} `json:"properties,required"`
Type EventListResponseEventServerConnectedType `json:"type,required"`
JSON eventListResponseEventServerConnectedJSON `json:"-"`
}
// eventListResponseEventServerConnectedJSON contains the JSON metadata for the
// struct [EventListResponseEventServerConnected]
type eventListResponseEventServerConnectedJSON struct {
Properties apijson.Field
Type apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *EventListResponseEventServerConnected) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r eventListResponseEventServerConnectedJSON) RawJSON() string {
return r.raw
}
func (r EventListResponseEventServerConnected) implementsEventListResponse() {}
type EventListResponseEventServerConnectedType string
const (
EventListResponseEventServerConnectedTypeServerConnected EventListResponseEventServerConnectedType = "server.connected"
)
func (r EventListResponseEventServerConnectedType) IsKnown() bool {
switch r {
case EventListResponseEventServerConnectedTypeServerConnected:
return true
}
return false
}
type EventListResponseEventFileWatcherUpdated struct {
Properties EventListResponseEventFileWatcherUpdatedProperties `json:"properties,required"`
Type EventListResponseEventFileWatcherUpdatedType `json:"type,required"`
@@ -1374,21 +1376,21 @@ const (
EventListResponseTypeMessagePartUpdated EventListResponseType = "message.part.updated"
EventListResponseTypeMessagePartRemoved EventListResponseType = "message.part.removed"
EventListResponseTypeStorageWrite EventListResponseType = "storage.write"
EventListResponseTypeFileEdited EventListResponseType = "file.edited"
EventListResponseTypeServerConnected EventListResponseType = "server.connected"
EventListResponseTypePermissionUpdated EventListResponseType = "permission.updated"
EventListResponseTypePermissionReplied EventListResponseType = "permission.replied"
EventListResponseTypeFileEdited EventListResponseType = "file.edited"
EventListResponseTypeSessionUpdated EventListResponseType = "session.updated"
EventListResponseTypeSessionDeleted EventListResponseType = "session.deleted"
EventListResponseTypeSessionIdle EventListResponseType = "session.idle"
EventListResponseTypeSessionError EventListResponseType = "session.error"
EventListResponseTypeServerConnected EventListResponseType = "server.connected"
EventListResponseTypeFileWatcherUpdated EventListResponseType = "file.watcher.updated"
EventListResponseTypeIdeInstalled EventListResponseType = "ide.installed"
)
func (r EventListResponseType) IsKnown() bool {
switch r {
case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeStorageWrite, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeFileEdited, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeServerConnected, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled:
case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeStorageWrite, EventListResponseTypeFileEdited, EventListResponseTypeServerConnected, EventListResponseTypePermissionUpdated, EventListResponseTypePermissionReplied, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled:
return true
}
return false
@@ -133,11 +133,13 @@ func NewRequestConfig(ctx context.Context, method string, u string, body interfa
// Fallback to json serialization if none of the serialization functions that we expect
// to see is present.
if body != nil && !hasSerializationFunc {
content, err := json.Marshal(body)
if err != nil {
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(true)
if err := enc.Encode(body); err != nil {
return nil, err
}
reader = bytes.NewBuffer(content)
reader = buf
}
req, err := http.NewRequestWithContext(ctx, method, u, nil)
+132 -14
View File
@@ -190,6 +190,113 @@ func (r *SessionService) Unshare(ctx context.Context, id string, opts ...option.
return
}
type AgentPart struct {
ID string `json:"id,required"`
MessageID string `json:"messageID,required"`
Name string `json:"name,required"`
SessionID string `json:"sessionID,required"`
Type AgentPartType `json:"type,required"`
Source AgentPartSource `json:"source"`
JSON agentPartJSON `json:"-"`
}
// agentPartJSON contains the JSON metadata for the struct [AgentPart]
type agentPartJSON struct {
ID apijson.Field
MessageID apijson.Field
Name apijson.Field
SessionID apijson.Field
Type apijson.Field
Source apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *AgentPart) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r agentPartJSON) RawJSON() string {
return r.raw
}
func (r AgentPart) implementsPart() {}
type AgentPartType string
const (
AgentPartTypeAgent AgentPartType = "agent"
)
func (r AgentPartType) IsKnown() bool {
switch r {
case AgentPartTypeAgent:
return true
}
return false
}
type AgentPartSource struct {
End int64 `json:"end,required"`
Start int64 `json:"start,required"`
Value string `json:"value,required"`
JSON agentPartSourceJSON `json:"-"`
}
// agentPartSourceJSON contains the JSON metadata for the struct [AgentPartSource]
type agentPartSourceJSON struct {
End apijson.Field
Start apijson.Field
Value apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
func (r *AgentPartSource) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
func (r agentPartSourceJSON) RawJSON() string {
return r.raw
}
type AgentPartInputParam struct {
Name param.Field[string] `json:"name,required"`
Type param.Field[AgentPartInputType] `json:"type,required"`
ID param.Field[string] `json:"id"`
Source param.Field[AgentPartInputSourceParam] `json:"source"`
}
func (r AgentPartInputParam) MarshalJSON() (data []byte, err error) {
return apijson.MarshalRoot(r)
}
func (r AgentPartInputParam) implementsSessionChatParamsPartUnion() {}
type AgentPartInputType string
const (
AgentPartInputTypeAgent AgentPartInputType = "agent"
)
func (r AgentPartInputType) IsKnown() bool {
switch r {
case AgentPartInputTypeAgent:
return true
}
return false
}
type AgentPartInputSourceParam struct {
End param.Field[int64] `json:"end,required"`
Start param.Field[int64] `json:"start,required"`
Value param.Field[string] `json:"value,required"`
}
func (r AgentPartInputSourceParam) MarshalJSON() (data []byte, err error) {
return apijson.MarshalRoot(r)
}
type AssistantMessage struct {
ID string `json:"id,required"`
Cost float64 `json:"cost,required"`
@@ -855,11 +962,13 @@ type Part struct {
Cost float64 `json:"cost"`
Filename string `json:"filename"`
// This field can have the runtime type of [[]string].
Files interface{} `json:"files"`
Hash string `json:"hash"`
Mime string `json:"mime"`
Snapshot string `json:"snapshot"`
Source FilePartSource `json:"source"`
Files interface{} `json:"files"`
Hash string `json:"hash"`
Mime string `json:"mime"`
Name string `json:"name"`
Snapshot string `json:"snapshot"`
// This field can have the runtime type of [FilePartSource], [AgentPartSource].
Source interface{} `json:"source"`
// This field can have the runtime type of [ToolPartState].
State interface{} `json:"state"`
Synthetic bool `json:"synthetic"`
@@ -886,6 +995,7 @@ type partJSON struct {
Files apijson.Field
Hash apijson.Field
Mime apijson.Field
Name apijson.Field
Snapshot apijson.Field
Source apijson.Field
State apijson.Field
@@ -916,13 +1026,13 @@ func (r *Part) UnmarshalJSON(data []byte) (err error) {
// for more type safety.
//
// Possible runtime types of the union are [TextPart], [FilePart], [ToolPart],
// [StepStartPart], [StepFinishPart], [SnapshotPart], [PartPatchPart].
// [StepStartPart], [StepFinishPart], [SnapshotPart], [PartPatchPart], [AgentPart].
func (r Part) AsUnion() PartUnion {
return r.union
}
// Union satisfied by [TextPart], [FilePart], [ToolPart], [StepStartPart],
// [StepFinishPart], [SnapshotPart] or [PartPatchPart].
// [StepFinishPart], [SnapshotPart], [PartPatchPart] or [AgentPart].
type PartUnion interface {
implementsPart()
}
@@ -966,6 +1076,11 @@ func init() {
Type: reflect.TypeOf(PartPatchPart{}),
DiscriminatorValue: "patch",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(AgentPart{}),
DiscriminatorValue: "agent",
},
)
}
@@ -1025,11 +1140,12 @@ const (
PartTypeStepFinish PartType = "step-finish"
PartTypeSnapshot PartType = "snapshot"
PartTypePatch PartType = "patch"
PartTypeAgent PartType = "agent"
)
func (r PartType) IsKnown() bool {
switch r {
case PartTypeText, PartTypeFile, PartTypeTool, PartTypeStepStart, PartTypeStepFinish, PartTypeSnapshot, PartTypePatch:
case PartTypeText, PartTypeFile, PartTypeTool, PartTypeStepStart, PartTypeStepFinish, PartTypeSnapshot, PartTypePatch, PartTypeAgent:
return true
}
return false
@@ -2080,8 +2196,8 @@ type SessionChatParams struct {
ModelID param.Field[string] `json:"modelID,required"`
Parts param.Field[[]SessionChatParamsPartUnion] `json:"parts,required"`
ProviderID param.Field[string] `json:"providerID,required"`
Agent param.Field[string] `json:"agent"`
MessageID param.Field[string] `json:"messageID"`
Mode param.Field[string] `json:"mode"`
System param.Field[string] `json:"system"`
Tools param.Field[map[string]bool] `json:"tools"`
}
@@ -2095,7 +2211,8 @@ type SessionChatParamsPart struct {
ID param.Field[string] `json:"id"`
Filename param.Field[string] `json:"filename"`
Mime param.Field[string] `json:"mime"`
Source param.Field[FilePartSourceUnionParam] `json:"source"`
Name param.Field[string] `json:"name"`
Source param.Field[interface{}] `json:"source"`
Synthetic param.Field[bool] `json:"synthetic"`
Text param.Field[string] `json:"text"`
Time param.Field[interface{}] `json:"time"`
@@ -2108,7 +2225,7 @@ func (r SessionChatParamsPart) MarshalJSON() (data []byte, err error) {
func (r SessionChatParamsPart) implementsSessionChatParamsPartUnion() {}
// Satisfied by [TextPartInputParam], [FilePartInputParam],
// Satisfied by [TextPartInputParam], [FilePartInputParam], [AgentPartInputParam],
// [SessionChatParamsPart].
type SessionChatParamsPartUnion interface {
implementsSessionChatParamsPartUnion()
@@ -2117,13 +2234,14 @@ type SessionChatParamsPartUnion interface {
type SessionChatParamsPartsType string
const (
SessionChatParamsPartsTypeText SessionChatParamsPartsType = "text"
SessionChatParamsPartsTypeFile SessionChatParamsPartsType = "file"
SessionChatParamsPartsTypeText SessionChatParamsPartsType = "text"
SessionChatParamsPartsTypeFile SessionChatParamsPartsType = "file"
SessionChatParamsPartsTypeAgent SessionChatParamsPartsType = "agent"
)
func (r SessionChatParamsPartsType) IsKnown() bool {
switch r {
case SessionChatParamsPartsTypeText, SessionChatParamsPartsTypeFile:
case SessionChatParamsPartsTypeText, SessionChatParamsPartsTypeFile, SessionChatParamsPartsTypeAgent:
return true
}
return false
+1 -1
View File
@@ -129,8 +129,8 @@ func TestSessionChatWithOptionalParams(t *testing.T) {
}),
}}),
ProviderID: opencode.F("providerID"),
Agent: opencode.F("agent"),
MessageID: opencode.F("msg"),
Mode: opencode.F("mode"),
System: opencode.F("system"),
Tools: opencode.F(map[string]bool{
"foo": true,
+1 -1
View File
@@ -47,7 +47,7 @@ func (r *TuiService) ClearPrompt(ctx context.Context, opts ...option.RequestOpti
return
}
// Execute a TUI command (e.g. switch_mode)
// Execute a TUI command (e.g. switch_agent)
func (r *TuiService) ExecuteCommand(ctx context.Context, body TuiExecuteCommandParams, opts ...option.RequestOption) (res *bool, err error) {
opts = append(r.Options[:], opts...)
path := "tui/execute-command"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/sdk",
"version": "0.3.113",
"version": "0.3.133",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit"
+1 -9
View File
@@ -4,16 +4,11 @@ const dir = new URL("..", import.meta.url).pathname
process.chdir(dir)
import { $ } from "bun"
import fs from "fs/promises"
import path from "path"
console.log("=== Generating JS SDK ===")
console.log()
import { createClient } from "@hey-api/openapi-ts"
await fs.rm(path.join(dir, "src/gen"), { recursive: true, force: true })
await $`bun run ./src/index.ts generate > openapi.json`.cwd(path.resolve(dir, "../../opencode"))
await $`bun dev generate > ${dir}/openapi.json`.cwd(path.resolve(dir, "../../opencode"))
await createClient({
input: "./openapi.json",
@@ -37,6 +32,3 @@ await createClient({
],
})
await $`bun prettier --write src/gen`
await $`rm -rf dist`
await $`bun tsc`
+2
View File
@@ -6,6 +6,8 @@ process.chdir(dir)
import { $ } from "bun"
await import("./generate")
await $`rm -rf dist`
await $`bun tsc`
const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true"
+12
View File
@@ -15,6 +15,8 @@ import type {
SessionCreateData,
SessionCreateResponses,
SessionCreateErrors,
SessionGetData,
SessionGetResponses,
SessionDeleteData,
SessionDeleteResponses,
SessionInitData,
@@ -202,6 +204,16 @@ class Session extends _HeyApiClient {
})
}
/**
* Get session
*/
public get<ThrowOnError extends boolean = false>(options: Options<SessionGetData, ThrowOnError>) {
return (options.client ?? this._client).get<SessionGetResponses, unknown, ThrowOnError>({
url: "/session/{sessionID}",
...options,
})
}
/**
* Delete a session and all its data
*/
+20 -1
View File
@@ -537,6 +537,7 @@ export type Config = {
theme?: string
keybinds?: KeybindsConfig
plugin?: Array<string>
snapshot?: boolean
/**
* Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing
*/
@@ -558,7 +559,7 @@ export type Config = {
*/
model?: string
/**
* Small model to use for tasks like summarization and title generation in the format of provider/model
* Small model to use for tasks like title generation in the format of provider/model
*/
small_model?: string
/**
@@ -1102,6 +1103,24 @@ export type SessionCreateResponses = {
export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses]
export type SessionGetData = {
body?: never
path: {
sessionID: string
}
query?: never
url: "/session/{sessionID}"
}
export type SessionGetResponses = {
/**
* Get session
*/
200: Session
}
export type SessionGetResponse = SessionGetResponses[keyof SessionGetResponses]
export type SessionDeleteData = {
body?: never
path: {
+9
View File
@@ -0,0 +1,9 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/* deno-fmt-ignore-file */
/// <reference path="../../../sst-env.d.ts" />
import "sst"
export {}
+3
View File
@@ -10,6 +10,9 @@
"es2022",
"dom",
"dom.iterable"
],
"customConditions": [
"development"
]
},
"include": [
@@ -1,44 +0,0 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
export {
Permissions,
type Permission,
type PermissionRespondResponse,
type PermissionRespondParams,
} from './permissions';
export {
SessionResource,
type AssistantMessage,
type FilePart,
type FilePartInput,
type FilePartSource,
type FilePartSourceText,
type FileSource,
type Message,
type Part,
type Session,
type SnapshotPart,
type StepFinishPart,
type StepStartPart,
type SymbolSource,
type TextPart,
type TextPartInput,
type ToolPart,
type ToolStateCompleted,
type ToolStateError,
type ToolStatePending,
type ToolStateRunning,
type UserMessage,
type SessionListResponse,
type SessionDeleteResponse,
type SessionAbortResponse,
type SessionInitResponse,
type SessionMessageResponse,
type SessionMessagesResponse,
type SessionSummarizeResponse,
type SessionChatParams,
type SessionInitParams,
type SessionMessageParams,
type SessionRevertParams,
type SessionSummarizeParams,
} from './session';
@@ -1,64 +0,0 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
import { APIResource } from '../../core/resource';
import { APIPromise } from '../../core/api-promise';
import { RequestOptions } from '../../internal/request-options';
import { path } from '../../internal/utils/path';
export class Permissions extends APIResource {
/**
* Respond to a permission request
*/
respond(
permissionID: string,
params: PermissionRespondParams,
options?: RequestOptions,
): APIPromise<PermissionRespondResponse> {
const { id, ...body } = params;
return this._client.post(path`/session/${id}/permissions/${permissionID}`, { body, ...options });
}
}
export interface Permission {
id: string;
messageID: string;
metadata: { [key: string]: unknown };
sessionID: string;
time: Permission.Time;
title: string;
toolCallID?: string;
}
export namespace Permission {
export interface Time {
created: number;
}
}
export type PermissionRespondResponse = boolean;
export interface PermissionRespondParams {
/**
* Path param:
*/
id: string;
/**
* Body param:
*/
response: 'once' | 'always' | 'reject';
}
export declare namespace Permissions {
export {
type Permission as Permission,
type PermissionRespondResponse as PermissionRespondResponse,
type PermissionRespondParams as PermissionRespondParams,
};
}
@@ -1,645 +0,0 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
import { APIResource } from '../../core/resource';
import * as SessionAPI from './session';
import * as Shared from '../shared';
import * as PermissionsAPI from './permissions';
import { Permission, PermissionRespondParams, PermissionRespondResponse, Permissions } from './permissions';
import { APIPromise } from '../../core/api-promise';
import { RequestOptions } from '../../internal/request-options';
import { path } from '../../internal/utils/path';
export class SessionResource extends APIResource {
permissions: PermissionsAPI.Permissions = new PermissionsAPI.Permissions(this._client);
/**
* Create a new session
*/
create(options?: RequestOptions): APIPromise<Session> {
return this._client.post('/session', options);
}
/**
* List all sessions
*/
list(options?: RequestOptions): APIPromise<SessionListResponse> {
return this._client.get('/session', options);
}
/**
* Delete a session and all its data
*/
delete(id: string, options?: RequestOptions): APIPromise<SessionDeleteResponse> {
return this._client.delete(path`/session/${id}`, options);
}
/**
* Abort a session
*/
abort(id: string, options?: RequestOptions): APIPromise<SessionAbortResponse> {
return this._client.post(path`/session/${id}/abort`, options);
}
/**
* Create and send a new message to a session
*/
chat(id: string, body: SessionChatParams, options?: RequestOptions): APIPromise<AssistantMessage> {
return this._client.post(path`/session/${id}/message`, { body, ...options });
}
/**
* Analyze the app and create an AGENTS.md file
*/
init(id: string, body: SessionInitParams, options?: RequestOptions): APIPromise<SessionInitResponse> {
return this._client.post(path`/session/${id}/init`, { body, ...options });
}
/**
* Get a message from a session
*/
message(
messageID: string,
params: SessionMessageParams,
options?: RequestOptions,
): APIPromise<SessionMessageResponse> {
const { id } = params;
return this._client.get(path`/session/${id}/message/${messageID}`, options);
}
/**
* List messages for a session
*/
messages(id: string, options?: RequestOptions): APIPromise<SessionMessagesResponse> {
return this._client.get(path`/session/${id}/message`, options);
}
/**
* Revert a message
*/
revert(id: string, body: SessionRevertParams, options?: RequestOptions): APIPromise<Session> {
return this._client.post(path`/session/${id}/revert`, { body, ...options });
}
/**
* Share a session
*/
share(id: string, options?: RequestOptions): APIPromise<Session> {
return this._client.post(path`/session/${id}/share`, options);
}
/**
* Summarize the session
*/
summarize(
id: string,
body: SessionSummarizeParams,
options?: RequestOptions,
): APIPromise<SessionSummarizeResponse> {
return this._client.post(path`/session/${id}/summarize`, { body, ...options });
}
/**
* Restore all reverted messages
*/
unrevert(id: string, options?: RequestOptions): APIPromise<Session> {
return this._client.post(path`/session/${id}/unrevert`, options);
}
/**
* Unshare the session
*/
unshare(id: string, options?: RequestOptions): APIPromise<Session> {
return this._client.delete(path`/session/${id}/share`, options);
}
}
export interface AssistantMessage {
id: string;
cost: number;
mode: string;
modelID: string;
path: AssistantMessage.Path;
providerID: string;
role: 'assistant';
sessionID: string;
system: Array<string>;
time: AssistantMessage.Time;
tokens: AssistantMessage.Tokens;
error?:
| Shared.ProviderAuthError
| Shared.UnknownError
| AssistantMessage.MessageOutputLengthError
| Shared.MessageAbortedError;
summary?: boolean;
}
export namespace AssistantMessage {
export interface Path {
cwd: string;
root: string;
}
export interface Time {
created: number;
completed?: number;
}
export interface Tokens {
cache: Tokens.Cache;
input: number;
output: number;
reasoning: number;
}
export namespace Tokens {
export interface Cache {
read: number;
write: number;
}
}
export interface MessageOutputLengthError {
data: unknown;
name: 'MessageOutputLengthError';
}
}
export interface FilePart {
id: string;
messageID: string;
mime: string;
sessionID: string;
type: 'file';
url: string;
filename?: string;
source?: FilePartSource;
}
export interface FilePartInput {
mime: string;
type: 'file';
url: string;
id?: string;
filename?: string;
source?: FilePartSource;
}
export type FilePartSource = FileSource | SymbolSource;
export interface FilePartSourceText {
end: number;
start: number;
value: string;
}
export interface FileSource {
path: string;
text: FilePartSourceText;
type: 'file';
}
export type Message = UserMessage | AssistantMessage;
export type Part =
| TextPart
| FilePart
| ToolPart
| StepStartPart
| StepFinishPart
| SnapshotPart
| Part.PatchPart;
export namespace Part {
export interface PatchPart {
id: string;
files: Array<string>;
hash: string;
messageID: string;
sessionID: string;
type: 'patch';
}
}
export interface Session {
id: string;
time: Session.Time;
title: string;
version: string;
parentID?: string;
revert?: Session.Revert;
share?: Session.Share;
}
export namespace Session {
export interface Time {
created: number;
updated: number;
}
export interface Revert {
messageID: string;
diff?: string;
partID?: string;
snapshot?: string;
}
export interface Share {
url: string;
}
}
export interface SnapshotPart {
id: string;
messageID: string;
sessionID: string;
snapshot: string;
type: 'snapshot';
}
export interface StepFinishPart {
id: string;
cost: number;
messageID: string;
sessionID: string;
tokens: StepFinishPart.Tokens;
type: 'step-finish';
}
export namespace StepFinishPart {
export interface Tokens {
cache: Tokens.Cache;
input: number;
output: number;
reasoning: number;
}
export namespace Tokens {
export interface Cache {
read: number;
write: number;
}
}
}
export interface StepStartPart {
id: string;
messageID: string;
sessionID: string;
type: 'step-start';
}
export interface SymbolSource {
kind: number;
name: string;
path: string;
range: SymbolSource.Range;
text: FilePartSourceText;
type: 'symbol';
}
export namespace SymbolSource {
export interface Range {
end: Range.End;
start: Range.Start;
}
export namespace Range {
export interface End {
character: number;
line: number;
}
export interface Start {
character: number;
line: number;
}
}
}
export interface TextPart {
id: string;
messageID: string;
sessionID: string;
text: string;
type: 'text';
synthetic?: boolean;
time?: TextPart.Time;
}
export namespace TextPart {
export interface Time {
start: number;
end?: number;
}
}
export interface TextPartInput {
text: string;
type: 'text';
id?: string;
synthetic?: boolean;
time?: TextPartInput.Time;
}
export namespace TextPartInput {
export interface Time {
start: number;
end?: number;
}
}
export interface ToolPart {
id: string;
callID: string;
messageID: string;
sessionID: string;
state: ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError;
tool: string;
type: 'tool';
}
export interface ToolStateCompleted {
input: { [key: string]: unknown };
metadata: { [key: string]: unknown };
output: string;
status: 'completed';
time: ToolStateCompleted.Time;
title: string;
}
export namespace ToolStateCompleted {
export interface Time {
end: number;
start: number;
}
}
export interface ToolStateError {
error: string;
input: { [key: string]: unknown };
status: 'error';
time: ToolStateError.Time;
}
export namespace ToolStateError {
export interface Time {
end: number;
start: number;
}
}
export interface ToolStatePending {
status: 'pending';
}
export interface ToolStateRunning {
status: 'running';
time: ToolStateRunning.Time;
input?: unknown;
metadata?: { [key: string]: unknown };
title?: string;
}
export namespace ToolStateRunning {
export interface Time {
start: number;
}
}
export interface UserMessage {
id: string;
role: 'user';
sessionID: string;
time: UserMessage.Time;
}
export namespace UserMessage {
export interface Time {
created: number;
}
}
export type SessionListResponse = Array<Session>;
export type SessionDeleteResponse = boolean;
export type SessionAbortResponse = boolean;
export type SessionInitResponse = boolean;
export interface SessionMessageResponse {
info: Message;
parts: Array<Part>;
}
export type SessionMessagesResponse = Array<SessionMessagesResponse.SessionMessagesResponseItem>;
export namespace SessionMessagesResponse {
export interface SessionMessagesResponseItem {
info: SessionAPI.Message;
parts: Array<SessionAPI.Part>;
}
}
export type SessionSummarizeResponse = boolean;
export interface SessionChatParams {
modelID: string;
parts: Array<TextPartInput | FilePartInput>;
providerID: string;
messageID?: string;
mode?: string;
system?: string;
tools?: { [key: string]: boolean };
}
export interface SessionInitParams {
messageID: string;
modelID: string;
providerID: string;
}
export interface SessionMessageParams {
/**
* Session ID
*/
id: string;
}
export interface SessionRevertParams {
messageID: string;
partID?: string;
}
export interface SessionSummarizeParams {
modelID: string;
providerID: string;
}
SessionResource.Permissions = Permissions;
export declare namespace SessionResource {
export {
type AssistantMessage as AssistantMessage,
type FilePart as FilePart,
type FilePartInput as FilePartInput,
type FilePartSource as FilePartSource,
type FilePartSourceText as FilePartSourceText,
type FileSource as FileSource,
type Message as Message,
type Part as Part,
type Session as Session,
type SnapshotPart as SnapshotPart,
type StepFinishPart as StepFinishPart,
type StepStartPart as StepStartPart,
type SymbolSource as SymbolSource,
type TextPart as TextPart,
type TextPartInput as TextPartInput,
type ToolPart as ToolPart,
type ToolStateCompleted as ToolStateCompleted,
type ToolStateError as ToolStateError,
type ToolStatePending as ToolStatePending,
type ToolStateRunning as ToolStateRunning,
type UserMessage as UserMessage,
type SessionListResponse as SessionListResponse,
type SessionDeleteResponse as SessionDeleteResponse,
type SessionAbortResponse as SessionAbortResponse,
type SessionInitResponse as SessionInitResponse,
type SessionMessageResponse as SessionMessageResponse,
type SessionMessagesResponse as SessionMessagesResponse,
type SessionSummarizeResponse as SessionSummarizeResponse,
type SessionChatParams as SessionChatParams,
type SessionInitParams as SessionInitParams,
type SessionMessageParams as SessionMessageParams,
type SessionRevertParams as SessionRevertParams,
type SessionSummarizeParams as SessionSummarizeParams,
};
export {
Permissions as Permissions,
type Permission as Permission,
type PermissionRespondResponse as PermissionRespondResponse,
type PermissionRespondParams as PermissionRespondParams,
};
}
+4 -2
View File
@@ -51,12 +51,12 @@ resources:
logLevel: LogLevel
provider: Provider
model: Model
mode: Mode
agent: Agent
methods:
get: get /app
init: post /app/init
log: post /log
modes: get /mode
agents: get /agent
providers: get /config/providers
find:
@@ -99,6 +99,8 @@ resources:
fileSource: FileSource
symbolSource: SymbolSource
toolPart: ToolPart
agentPart: AgentPart
agentPartInput: AgentPartInput
stepStartPart: StepStartPart
stepFinishPart: StepFinishPart
snapshotPart: SnapshotPart
@@ -1,27 +0,0 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
import Opencode from '@opencode-ai/sdk';
const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
describe('resource permissions', () => {
// skipped: tests are disabled for the time being
test.skip('respond: only required params', async () => {
const responsePromise = client.session.permissions.respond('permissionID', {
id: 'id',
response: 'once',
});
const rawResponse = await responsePromise.asResponse();
expect(rawResponse).toBeInstanceOf(Response);
const response = await responsePromise;
expect(response).not.toBeInstanceOf(Response);
const dataAndResponse = await responsePromise.withResponse();
expect(dataAndResponse.data).toBe(response);
expect(dataAndResponse.response).toBe(rawResponse);
});
// skipped: tests are disabled for the time being
test.skip('respond: required and optional params', async () => {
const response = await client.session.permissions.respond('permissionID', { id: 'id', response: 'once' });
});
});
+6 -6
View File
@@ -31,7 +31,7 @@ func main() {
var model *string = flag.String("model", "", "model to begin with")
var prompt *string = flag.String("prompt", "", "prompt to begin with")
var mode *string = flag.String("mode", "", "mode to begin with")
var agent *string = flag.String("agent", "", "agent to begin with")
flag.Parse()
url := os.Getenv("OPENCODE_SERVER")
@@ -44,9 +44,9 @@ func main() {
os.Exit(1)
}
modesStr := os.Getenv("OPENCODE_MODES")
var modes []opencode.Mode
err = json.Unmarshal([]byte(modesStr), &modes)
agentsStr := os.Getenv("OPENCODE_AGENTS")
var agents []opencode.Agent
err = json.Unmarshal([]byte(agentsStr), &agents)
if err != nil {
slog.Error("Failed to unmarshal modes", "error", err)
os.Exit(1)
@@ -86,7 +86,7 @@ func main() {
logger := slog.New(apiHandler)
slog.SetDefault(logger)
slog.Debug("TUI launched", "app", appInfoStr, "modes", modesStr, "url", url)
slog.Debug("TUI launched", "app", appInfoStr, "modes", agentsStr, "url", url)
go func() {
err = clipboard.Init()
@@ -96,7 +96,7 @@ func main() {
}()
// Create main context for the application
app_, err := app.New(ctx, version, appInfo, modes, httpClient, model, prompt, mode)
app_, err := app.New(ctx, version, appInfo, agents, httpClient, model, prompt, agent)
if err != nil {
panic(err)
}
+91 -50
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"log/slog"
@@ -27,15 +28,14 @@ type Message struct {
type App struct {
Info opencode.App
Modes []opencode.Mode
Agents []opencode.Agent
Providers []opencode.Provider
Version string
StatePath string
Config *opencode.Config
Client *opencode.Client
State *State
ModeIndex int
Mode *opencode.Mode
AgentIndex int
Provider *opencode.Provider
Model *opencode.Model
Session *opencode.Session
@@ -45,11 +45,15 @@ type App struct {
Commands commands.CommandRegistry
InitialModel *string
InitialPrompt *string
IntitialMode *string
InitialAgent *string
compactCancel context.CancelFunc
IsLeaderSequence bool
}
func (a *App) Agent() *opencode.Agent {
return &a.Agents[a.AgentIndex]
}
type SessionCreatedMsg = struct {
Session *opencode.Session
}
@@ -83,11 +87,11 @@ func New(
ctx context.Context,
version string,
appInfo opencode.App,
modes []opencode.Mode,
agents []opencode.Agent,
httpClient *opencode.Client,
initialModel *string,
initialPrompt *string,
initialMode *string,
initialAgent *string,
) (*App, error) {
util.RootPath = appInfo.Path.Root
util.CwdPath = appInfo.Path.Cwd
@@ -108,8 +112,8 @@ func New(
SaveState(appStatePath, appState)
}
if appState.ModeModel == nil {
appState.ModeModel = make(map[string]ModeModel)
if appState.AgentModel == nil {
appState.AgentModel = make(map[string]AgentModel)
}
if configInfo.Theme != "" {
@@ -121,27 +125,29 @@ func New(
appState.Theme = themeEnv
}
var modeIndex int
var mode *opencode.Mode
agentIndex := slices.IndexFunc(agents, func(a opencode.Agent) bool {
return a.Mode != "subagent"
})
var agent *opencode.Agent
modeName := "build"
if appState.Mode != "" {
modeName = appState.Mode
if appState.Agent != "" {
modeName = appState.Agent
}
if initialMode != nil && *initialMode != "" {
modeName = *initialMode
if initialAgent != nil && *initialAgent != "" {
modeName = *initialAgent
}
for i, m := range modes {
for i, m := range agents {
if m.Name == modeName {
modeIndex = i
agentIndex = i
break
}
}
mode = &modes[modeIndex]
agent = &agents[agentIndex]
if mode.Model.ModelID != "" {
appState.ModeModel[mode.Name] = ModeModel{
ProviderID: mode.Model.ProviderID,
ModelID: mode.Model.ModelID,
if agent.Model.ModelID != "" {
appState.AgentModel[agent.Name] = AgentModel{
ProviderID: agent.Model.ProviderID,
ModelID: agent.Model.ModelID,
}
}
@@ -167,20 +173,19 @@ func New(
app := &App{
Info: appInfo,
Modes: modes,
Agents: agents,
Version: version,
StatePath: appStatePath,
Config: configInfo,
State: appState,
Client: httpClient,
ModeIndex: modeIndex,
Mode: mode,
AgentIndex: agentIndex,
Session: &opencode.Session{},
Messages: []Message{},
Commands: commands.LoadFromConfig(configInfo),
InitialModel: initialModel,
InitialPrompt: initialPrompt,
IntitialMode: initialMode,
InitialAgent: initialAgent,
}
return app, nil
@@ -222,22 +227,24 @@ func SetClipboard(text string) tea.Cmd {
func (a *App) cycleMode(forward bool) (*App, tea.Cmd) {
if forward {
a.ModeIndex++
if a.ModeIndex >= len(a.Modes) {
a.ModeIndex = 0
a.AgentIndex++
if a.AgentIndex >= len(a.Agents) {
a.AgentIndex = 0
}
} else {
a.ModeIndex--
if a.ModeIndex < 0 {
a.ModeIndex = len(a.Modes) - 1
a.AgentIndex--
if a.AgentIndex < 0 {
a.AgentIndex = len(a.Agents) - 1
}
}
a.Mode = &a.Modes[a.ModeIndex]
if a.Agent().Mode == "subagent" {
return a.cycleMode(forward)
}
modelID := a.Mode.Model.ModelID
providerID := a.Mode.Model.ProviderID
modelID := a.Agent().Model.ModelID
providerID := a.Agent().Model.ProviderID
if modelID == "" {
if model, ok := a.State.ModeModel[a.Mode.Name]; ok {
if model, ok := a.State.AgentModel[a.Agent().Name]; ok {
modelID = model.ModelID
providerID = model.ProviderID
}
@@ -258,20 +265,23 @@ func (a *App) cycleMode(forward bool) (*App, tea.Cmd) {
}
}
a.State.Mode = a.Mode.Name
a.State.Agent = a.Agent().Name
return a, a.SaveState()
}
func (a *App) SwitchMode() (*App, tea.Cmd) {
func (a *App) SwitchAgent() (*App, tea.Cmd) {
return a.cycleMode(true)
}
func (a *App) SwitchModeReverse() (*App, tea.Cmd) {
func (a *App) SwitchAgentReverse() (*App, tea.Cmd) {
return a.cycleMode(false)
}
// findModelByFullID finds a model by its full ID in the format "provider/model"
func findModelByFullID(providers []opencode.Provider, fullModelID string) (*opencode.Provider, *opencode.Model) {
func findModelByFullID(
providers []opencode.Provider,
fullModelID string,
) (*opencode.Provider, *opencode.Model) {
modelParts := strings.SplitN(fullModelID, "/", 2)
if len(modelParts) < 2 {
return nil, nil
@@ -284,7 +294,10 @@ func findModelByFullID(providers []opencode.Provider, fullModelID string) (*open
}
// findModelByProviderAndModelID finds a model by provider ID and model ID
func findModelByProviderAndModelID(providers []opencode.Provider, providerID, modelID string) (*opencode.Provider, *opencode.Model) {
func findModelByProviderAndModelID(
providers []opencode.Provider,
providerID, modelID string,
) (*opencode.Provider, *opencode.Model) {
for _, provider := range providers {
if provider.ID != providerID {
continue
@@ -330,7 +343,7 @@ func (a *App) InitializeProvider() tea.Cmd {
a.Providers = providers
// retains backwards compatibility with old state format
if model, ok := a.State.ModeModel[a.State.Mode]; ok {
if model, ok := a.State.AgentModel[a.State.Agent]; ok {
a.State.Provider = model.ProviderID
a.State.Model = model.ModelID
}
@@ -340,10 +353,17 @@ func (a *App) InitializeProvider() tea.Cmd {
// Priority 1: Command line --model flag (InitialModel)
if a.InitialModel != nil && *a.InitialModel != "" {
if provider, model := findModelByFullID(providers, *a.InitialModel); provider != nil && model != nil {
if provider, model := findModelByFullID(providers, *a.InitialModel); provider != nil &&
model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from command line", "provider", provider.ID, "model", model.ID)
slog.Debug(
"Selected model from command line",
"provider",
provider.ID,
"model",
model.ID,
)
} else {
slog.Debug("Command line model not found", "model", *a.InitialModel)
}
@@ -351,7 +371,8 @@ func (a *App) InitializeProvider() tea.Cmd {
// Priority 2: Config file model setting
if selectedProvider == nil && a.Config.Model != "" {
if provider, model := findModelByFullID(providers, a.Config.Model); provider != nil && model != nil {
if provider, model := findModelByFullID(providers, a.Config.Model); provider != nil &&
model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from config", "provider", provider.ID, "model", model.ID)
@@ -363,10 +384,17 @@ func (a *App) InitializeProvider() tea.Cmd {
// Priority 3: Recent model usage (most recently used model)
if selectedProvider == nil && len(a.State.RecentlyUsedModels) > 0 {
recentUsage := a.State.RecentlyUsedModels[0] // Most recent is first
if provider, model := findModelByProviderAndModelID(providers, recentUsage.ProviderID, recentUsage.ModelID); provider != nil && model != nil {
if provider, model := findModelByProviderAndModelID(providers, recentUsage.ProviderID, recentUsage.ModelID); provider != nil &&
model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from recent usage", "provider", provider.ID, "model", model.ID)
slog.Debug(
"Selected model from recent usage",
"provider",
provider.ID,
"model",
model.ID,
)
} else {
slog.Debug("Recent model not found", "provider", recentUsage.ProviderID, "model", recentUsage.ModelID)
}
@@ -374,7 +402,8 @@ func (a *App) InitializeProvider() tea.Cmd {
// Priority 4: State-based model (backwards compatibility)
if selectedProvider == nil && a.State.Provider != "" && a.State.Model != "" {
if provider, model := findModelByProviderAndModelID(providers, a.State.Provider, a.State.Model); provider != nil && model != nil {
if provider, model := findModelByProviderAndModelID(providers, a.State.Provider, a.State.Model); provider != nil &&
model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from state", "provider", provider.ID, "model", model.ID)
@@ -390,7 +419,13 @@ func (a *App) InitializeProvider() tea.Cmd {
if model := getDefaultModel(providersResponse, *provider); model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from internal priority (Anthropic)", "provider", provider.ID, "model", model.ID)
slog.Debug(
"Selected model from internal priority (Anthropic)",
"provider",
provider.ID,
"model",
model.ID,
)
}
}
@@ -400,7 +435,13 @@ func (a *App) InitializeProvider() tea.Cmd {
if model := getDefaultModel(providersResponse, *provider); model != nil {
selectedProvider = provider
selectedModel = model
slog.Debug("Selected model from fallback (first available)", "provider", provider.ID, "model", model.ID)
slog.Debug(
"Selected model from fallback (first available)",
"provider",
provider.ID,
"model",
model.ID,
)
}
}
}
@@ -552,7 +593,7 @@ func (a *App) SendPrompt(ctx context.Context, prompt Prompt) (*App, tea.Cmd) {
_, err := a.Client.Session.Chat(ctx, a.Session.ID, opencode.SessionChatParams{
ProviderID: opencode.F(a.Provider.ID),
ModelID: opencode.F(a.Model.ID),
Mode: opencode.F(a.Mode.Name),
Agent: opencode.F(a.Agent().Name),
MessageID: opencode.F(messageID),
Parts: opencode.F(message.ToSessionChatParams()),
})
+38 -61
View File
@@ -55,6 +55,22 @@ func (p Prompt) ToMessage(
Text: text,
}}
for _, attachment := range p.Attachments {
if attachment.Type == "agent" {
source, _ := attachment.GetAgentSource()
parts = append(parts, opencode.AgentPart{
ID: id.Ascending(id.Part),
MessageID: messageID,
SessionID: sessionID,
Name: source.Name,
Source: opencode.AgentPartSource{
Value: attachment.Display,
Start: int64(attachment.StartIndex),
End: int64(attachment.EndIndex),
},
})
continue
}
text := opencode.FilePartSourceText{
Start: int64(attachment.StartIndex),
End: int64(attachment.EndIndex),
@@ -122,6 +138,17 @@ func (m Message) ToPrompt() (*Prompt, error) {
continue
}
text += p.Text + " "
case opencode.AgentPart:
attachments = append(attachments, &attachment.Attachment{
ID: p.ID,
Type: "agent",
Display: p.Source.Value,
StartIndex: int(p.Source.Start),
EndIndex: int(p.Source.End),
Source: &attachment.AgentSource{
Name: p.Name,
},
})
case opencode.FilePart:
switch p.Source.Type {
case "file":
@@ -236,68 +263,18 @@ func (m Message) ToSessionChatParams() []opencode.SessionChatParamsPartUnion {
Filename: opencode.F(p.Filename),
Source: opencode.F(source),
})
case opencode.AgentPart:
parts = append(parts, opencode.AgentPartInputParam{
ID: opencode.F(p.ID),
Type: opencode.F(opencode.AgentPartInputTypeAgent),
Name: opencode.F(p.Name),
Source: opencode.F(opencode.AgentPartInputSourceParam{
Value: opencode.F(p.Source.Value),
Start: opencode.F(p.Source.Start),
End: opencode.F(p.Source.End),
}),
})
}
}
return parts
}
func (p Prompt) ToSessionChatParams() []opencode.SessionChatParamsPartUnion {
parts := []opencode.SessionChatParamsPartUnion{
opencode.TextPartInputParam{
Type: opencode.F(opencode.TextPartInputTypeText),
Text: opencode.F(p.Text),
},
}
for _, att := range p.Attachments {
filePart := opencode.FilePartInputParam{
Type: opencode.F(opencode.FilePartInputTypeFile),
Mime: opencode.F(att.MediaType),
URL: opencode.F(att.URL),
Filename: opencode.F(att.Filename),
}
switch att.Type {
case "file":
if fs, ok := att.GetFileSource(); ok {
filePart.Source = opencode.F(
opencode.FilePartSourceUnionParam(opencode.FileSourceParam{
Type: opencode.F(opencode.FileSourceTypeFile),
Path: opencode.F(fs.Path),
Text: opencode.F(opencode.FilePartSourceTextParam{
Start: opencode.F(int64(att.StartIndex)),
End: opencode.F(int64(att.EndIndex)),
Value: opencode.F(att.Display),
}),
}),
)
}
case "symbol":
if ss, ok := att.GetSymbolSource(); ok {
filePart.Source = opencode.F(
opencode.FilePartSourceUnionParam(opencode.SymbolSourceParam{
Type: opencode.F(opencode.SymbolSourceTypeSymbol),
Path: opencode.F(ss.Path),
Name: opencode.F(ss.Name),
Kind: opencode.F(int64(ss.Kind)),
Range: opencode.F(opencode.SymbolSourceRangeParam{
Start: opencode.F(opencode.SymbolSourceRangeStartParam{
Line: opencode.F(float64(ss.Range.Start.Line)),
Character: opencode.F(float64(ss.Range.Start.Char)),
}),
End: opencode.F(opencode.SymbolSourceRangeEndParam{
Line: opencode.F(float64(ss.Range.End.Line)),
Character: opencode.F(float64(ss.Range.End.Char)),
}),
}),
Text: opencode.F(opencode.FilePartSourceTextParam{
Start: opencode.F(int64(att.StartIndex)),
End: opencode.F(int64(att.EndIndex)),
Value: opencode.F(att.Display),
}),
}),
)
}
}
parts = append(parts, filePart)
}
return parts
}
+13 -13
View File
@@ -16,29 +16,29 @@ type ModelUsage struct {
LastUsed time.Time `toml:"last_used"`
}
type ModeModel struct {
type AgentModel struct {
ProviderID string `toml:"provider_id"`
ModelID string `toml:"model_id"`
}
type State struct {
Theme string `toml:"theme"`
ScrollSpeed *int `toml:"scroll_speed"`
ModeModel map[string]ModeModel `toml:"mode_model"`
Provider string `toml:"provider"`
Model string `toml:"model"`
Mode string `toml:"mode"`
RecentlyUsedModels []ModelUsage `toml:"recently_used_models"`
MessagesRight bool `toml:"messages_right"`
SplitDiff bool `toml:"split_diff"`
MessageHistory []Prompt `toml:"message_history"`
Theme string `toml:"theme"`
ScrollSpeed *int `toml:"scroll_speed"`
AgentModel map[string]AgentModel `toml:"agent_model"`
Provider string `toml:"provider"`
Model string `toml:"model"`
Agent string `toml:"agent"`
RecentlyUsedModels []ModelUsage `toml:"recently_used_models"`
MessagesRight bool `toml:"messages_right"`
SplitDiff bool `toml:"split_diff"`
MessageHistory []Prompt `toml:"message_history"`
}
func NewState() *State {
return &State{
Theme: "opencode",
Mode: "build",
ModeModel: make(map[string]ModeModel),
Agent: "build",
AgentModel: make(map[string]AgentModel),
RecentlyUsedModels: make([]ModelUsage, 0),
MessageHistory: make([]Prompt, 0),
}
@@ -26,6 +26,10 @@ type SymbolRange struct {
End Position `toml:"end"`
}
type AgentSource struct {
Name string `toml:"name"`
}
type Position struct {
Line int `toml:"line"`
Char int `toml:"char"`
@@ -76,6 +80,15 @@ func (a *Attachment) GetSymbolSource() (*SymbolSource, bool) {
return ss, ok
}
// GetAgentSource returns the source as AgentSource if the attachment is an agent type
func (a *Attachment) GetAgentSource() (*AgentSource, bool) {
if a.Type != "agent" {
return nil, false
}
as, ok := a.Source.(*AgentSource)
return as, ok
}
// FromMap creates a TextSource from a map[string]any
func (ts *TextSource) FromMap(sourceMap map[string]any) {
if value, ok := sourceMap["value"].(string); ok {
@@ -128,6 +141,13 @@ func (ss *SymbolSource) FromMap(sourceMap map[string]any) {
}
}
// FromMap creates an AgentSource from a map[string]any
func (as *AgentSource) FromMap(sourceMap map[string]any) {
if name, ok := sourceMap["name"].(string); ok {
as.Name = name
}
}
// RestoreSourceType converts a map[string]any source back to the proper type
func (a *Attachment) RestoreSourceType() {
if a.Source == nil {
@@ -149,6 +169,10 @@ func (a *Attachment) RestoreSourceType() {
ss := &SymbolSource{}
ss.FromMap(sourceMap)
a.Source = ss
case "agent":
as := &AgentSource{}
as.FromMap(sourceMap)
a.Source = as
}
}
}
+6 -6
View File
@@ -107,8 +107,8 @@ func (r CommandRegistry) Matches(msg tea.KeyPressMsg, leader bool) []Command {
const (
AppHelpCommand CommandName = "app_help"
SwitchModeCommand CommandName = "switch_mode"
SwitchModeReverseCommand CommandName = "switch_mode_reverse"
SwitchAgentCommand CommandName = "switch_agent"
SwitchAgentReverseCommand CommandName = "switch_agent_reverse"
EditorOpenCommand CommandName = "editor_open"
SessionNewCommand CommandName = "session_new"
SessionListCommand CommandName = "session_list"
@@ -181,13 +181,13 @@ func LoadFromConfig(config *opencode.Config) CommandRegistry {
Trigger: []string{"help"},
},
{
Name: SwitchModeCommand,
Description: "next mode",
Name: SwitchAgentCommand,
Description: "next agent",
Keybindings: parseBindings("tab"),
},
{
Name: SwitchModeReverseCommand,
Description: "previous mode",
Name: SwitchAgentReverseCommand,
Description: "previous agent",
Keybindings: parseBindings("shift+tab"),
},
{
@@ -0,0 +1,74 @@
package completions
import (
"context"
"log/slog"
"strings"
"github.com/sst/opencode-sdk-go"
"github.com/sst/opencode/internal/app"
"github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
)
type agentsContextGroup struct {
app *app.App
}
func (cg *agentsContextGroup) GetId() string {
return "agents"
}
func (cg *agentsContextGroup) GetEmptyMessage() string {
return "no matching agents"
}
func (cg *agentsContextGroup) GetChildEntries(
query string,
) ([]CompletionSuggestion, error) {
items := make([]CompletionSuggestion, 0)
query = strings.TrimSpace(query)
agents, err := cg.app.Client.App.Agents(
context.Background(),
)
if err != nil {
slog.Error("Failed to get agent list", "error", err)
return items, err
}
if agents == nil {
return items, nil
}
for _, agent := range *agents {
if query != "" && !strings.Contains(strings.ToLower(agent.Name), strings.ToLower(query)) {
continue
}
if agent.Mode == opencode.AgentModePrimary || agent.Name == "general" {
continue
}
displayFunc := func(s styles.Style) string {
t := theme.CurrentTheme()
muted := s.Foreground(t.TextMuted()).Render
return s.Render(agent.Name) + muted(" (agent)")
}
item := CompletionSuggestion{
Display: displayFunc,
Value: agent.Name,
ProviderID: cg.GetId(),
RawData: agent,
}
items = append(items, item)
}
return items, nil
}
func NewAgentsContextGroup(app *app.App) CompletionProvider {
return &agentsContextGroup{
app: app,
}
}
@@ -288,6 +288,31 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.textarea.InsertAttachment(attachment)
m.textarea.InsertString(" ")
return m, nil
case "agents":
atIndex := m.textarea.LastRuneIndex('@')
if atIndex == -1 {
// Should not happen, but as a fallback, just insert.
m.textarea.InsertString(msg.Item.Value + " ")
return m, nil
}
cursorCol := m.textarea.CursorColumn()
m.textarea.ReplaceRange(atIndex, cursorCol, "")
name := msg.Item.Value
attachment := &attachment.Attachment{
ID: uuid.NewString(),
Type: "agent",
Display: "@" + name,
Source: &attachment.AgentSource{
Name: name,
},
}
m.textarea.InsertAttachment(attachment)
m.textarea.InsertString(" ")
return m, nil
default:
slog.Debug("Unknown provider", "provider", msg.Item.ProviderID)
return m, nil
@@ -23,17 +23,18 @@ import (
)
type blockRenderer struct {
textColor compat.AdaptiveColor
border bool
borderColor *compat.AdaptiveColor
borderLeft bool
borderRight bool
paddingTop int
paddingBottom int
paddingLeft int
paddingRight int
marginTop int
marginBottom int
textColor compat.AdaptiveColor
backgroundColor compat.AdaptiveColor
border bool
borderColor *compat.AdaptiveColor
borderLeft bool
borderRight bool
paddingTop int
paddingBottom int
paddingLeft int
paddingRight int
marginTop int
marginBottom int
}
type renderingOption func(*blockRenderer)
@@ -44,6 +45,12 @@ func WithTextColor(color compat.AdaptiveColor) renderingOption {
}
}
func WithBackgroundColor(color compat.AdaptiveColor) renderingOption {
return func(c *blockRenderer) {
c.backgroundColor = color
}
}
func WithNoBorder() renderingOption {
return func(c *blockRenderer) {
c.border = false
@@ -132,14 +139,15 @@ func renderContentBlock(
) string {
t := theme.CurrentTheme()
renderer := &blockRenderer{
textColor: t.TextMuted(),
border: true,
borderLeft: true,
borderRight: false,
paddingTop: 1,
paddingBottom: 1,
paddingLeft: 2,
paddingRight: 2,
textColor: t.TextMuted(),
backgroundColor: t.BackgroundPanel(),
border: true,
borderLeft: true,
borderRight: false,
paddingTop: 1,
paddingBottom: 1,
paddingLeft: 2,
paddingRight: 2,
}
for _, option := range options {
option(renderer)
@@ -152,7 +160,7 @@ func renderContentBlock(
style := styles.NewStyle().
Foreground(renderer.textColor).
Background(t.BackgroundPanel()).
Background(renderer.backgroundColor).
PaddingTop(renderer.paddingTop).
PaddingBottom(renderer.paddingBottom).
PaddingLeft(renderer.paddingLeft).
@@ -201,6 +209,7 @@ func renderText(
width int,
extra string,
fileParts []opencode.FilePart,
agentParts []opencode.AgentPart,
toolCalls ...opencode.ToolPart,
) string {
t := theme.CurrentTheme()
@@ -211,40 +220,89 @@ func renderText(
switch casted := message.(type) {
case opencode.AssistantMessage:
ts = time.UnixMilli(int64(casted.Time.Created))
content = util.ToMarkdown(text, width, backgroundColor)
content = util.ToMarkdown(text, width, t.Background())
case opencode.UserMessage:
ts = time.UnixMilli(int64(casted.Time.Created))
base := styles.NewStyle().Foreground(t.Text()).Background(backgroundColor)
text = ansi.WordwrapWc(text, width-6, " -")
var result strings.Builder
lastEnd := int64(0)
// Apply highlighting to filenames and base style to rest of text
// Apply highlighting to filenames and base style to rest of text BEFORE wrapping
textLen := int64(len(text))
// Collect all parts to highlight (both file and agent parts)
type highlightPart struct {
start int64
end int64
color compat.AdaptiveColor
}
var highlights []highlightPart
// Add file parts with secondary color
for _, filePart := range fileParts {
highlight := base.Foreground(t.Secondary())
start, end := filePart.Source.Text.Start, filePart.Source.Text.End
highlights = append(highlights, highlightPart{
start: filePart.Source.Text.Start,
end: filePart.Source.Text.End,
color: t.Secondary(),
})
}
// Add agent parts with secondary color (same as file parts)
for _, agentPart := range agentParts {
highlights = append(highlights, highlightPart{
start: agentPart.Source.Start,
end: agentPart.Source.End,
color: t.Secondary(),
})
}
// Sort highlights by start position
slices.SortFunc(highlights, func(a, b highlightPart) int {
if a.start < b.start {
return -1
}
if a.start > b.start {
return 1
}
return 0
})
for _, part := range highlights {
highlight := base.Foreground(part.color)
start, end := part.start, part.end
if end > textLen {
end = textLen
}
if start > textLen {
start = textLen
}
if start > lastEnd {
result.WriteString(base.Render(text[lastEnd:start]))
}
result.WriteString(highlight.Render(text[start:end]))
if start < end {
result.WriteString(highlight.Render(text[start:end]))
}
lastEnd = end
}
if lastEnd < int64(len(text)) {
if lastEnd < textLen {
result.WriteString(base.Render(text[lastEnd:]))
}
content = base.Width(width - 6).Render(result.String())
// wrap styled text
styledText := result.String()
wrappedText := ansi.WordwrapWc(styledText, width-6, " -")
content = base.Width(width - 6).Render(wrappedText)
}
timestamp := ts.
Local().
Format("02 Jan 2006 03:04 PM")
if time.Now().Format("02 Jan 2006") == timestamp[:11] {
// don't show the date if it's today
timestamp = timestamp[12:]
}
info := fmt.Sprintf("%s (%s)", author, timestamp)
@@ -278,14 +336,14 @@ func renderText(
width,
WithTextColor(t.Text()),
WithBorderColor(t.Secondary()),
WithBorderRight(),
)
case opencode.AssistantMessage:
return renderContentBlock(
app,
content,
width,
WithBorderColor(t.Accent()),
WithNoBorder(),
WithBackgroundColor(t.Background()),
)
}
return ""
@@ -358,8 +416,8 @@ func renderToolDetails(
}
if permission.Metadata != nil {
metadata := toolCall.State.Metadata.(map[string]any)
if metadata == nil {
metadata, ok := toolCall.State.Metadata.(map[string]any)
if metadata == nil || !ok {
metadata = map[string]any{}
}
maps.Copy(metadata, permission.Metadata)
@@ -555,6 +613,8 @@ func renderToolName(name string) string {
switch name {
case "webfetch":
return "Fetch"
case "invalid":
return "Invalid"
default:
normalizedName := name
if after, ok := strings.CutPrefix(name, "opencode_"); ok {
@@ -657,6 +717,10 @@ func renderToolTitle(
title = getTodoTitle(toolCall)
case "todoread":
return "Plan"
case "invalid":
if actualTool, ok := toolArgsMap["tool"].(string); ok {
title = renderToolName(actualTool)
}
default:
toolName := renderToolName(toolCall.Tool)
title = fmt.Sprintf("%s %s", toolName, toolArgs)
@@ -300,10 +300,17 @@ func (m *messagesComponent) renderView() tea.Cmd {
}
remainingParts := message.Parts[partIndex+1:]
fileParts := make([]opencode.FilePart, 0)
agentParts := make([]opencode.AgentPart, 0)
for _, part := range remainingParts {
switch part := part.(type) {
case opencode.FilePart:
fileParts = append(fileParts, part)
if part.Source.Text.Start >= 0 && part.Source.Text.End >= part.Source.Text.Start {
fileParts = append(fileParts, part)
}
case opencode.AgentPart:
if part.Source.Start >= 0 && part.Source.End >= part.Source.Start {
agentParts = append(agentParts, part)
}
}
}
flexItems := []layout.FlexItem{}
@@ -353,6 +360,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
width,
files,
fileParts,
agentParts,
)
content = lipgloss.PlaceHorizontal(
m.width,
@@ -431,6 +439,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
width,
"",
[]opencode.FilePart{},
[]opencode.AgentPart{},
toolCallParts...,
)
content = lipgloss.PlaceHorizontal(
@@ -451,6 +460,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
width,
"",
[]opencode.FilePart{},
[]opencode.AgentPart{},
toolCallParts...,
)
content = lipgloss.PlaceHorizontal(
@@ -66,11 +66,16 @@ func (c *completionDialogComponent) Init() tea.Cmd {
func (c *completionDialogComponent) getAllCompletions(query string) tea.Cmd {
return func() tea.Msg {
allItems := make([]completions.CompletionSuggestion, 0)
// Collect results from all providers and preserve provider order
type providerItems struct {
idx int
items []completions.CompletionSuggestion
}
itemsByProvider := make([]providerItems, 0, len(c.providers))
providersWithResults := 0
// Collect results from all providers
for _, provider := range c.providers {
for idx, provider := range c.providers {
items, err := provider.GetChildEntries(query)
if err != nil {
slog.Error(
@@ -84,33 +89,46 @@ func (c *completionDialogComponent) getAllCompletions(query string) tea.Cmd {
}
if len(items) > 0 {
providersWithResults++
allItems = append(allItems, items...)
itemsByProvider = append(itemsByProvider, providerItems{idx: idx, items: items})
}
}
// If there's a query, use fuzzy ranking to sort results
if query != "" && providersWithResults > 1 {
// If there's a query, fuzzy-rank within each provider, then concatenate by provider order
if query != "" && providersWithResults > 0 {
t := theme.CurrentTheme()
baseStyle := styles.NewStyle().Background(t.BackgroundElement())
// Create a slice of display values for fuzzy matching
displayValues := make([]string, len(allItems))
for i, item := range allItems {
displayValues[i] = item.Display(baseStyle)
// Ensure stable provider order just in case
sort.SliceStable(itemsByProvider, func(i, j int) bool { return itemsByProvider[i].idx < itemsByProvider[j].idx })
final := make([]completions.CompletionSuggestion, 0)
for _, entry := range itemsByProvider {
// Build display values for fuzzy matching within this provider
displayValues := make([]string, len(entry.items))
for i, item := range entry.items {
displayValues[i] = item.Display(baseStyle)
}
matches := fuzzy.RankFindFold(query, displayValues)
sort.Sort(matches)
// Reorder items for this provider based on fuzzy ranking
ranked := make([]completions.CompletionSuggestion, 0, len(matches))
for _, m := range matches {
ranked = append(ranked, entry.items[m.OriginalIndex])
}
final = append(final, ranked...)
}
matches := fuzzy.RankFindFold(query, displayValues)
sort.Sort(matches)
// Reorder items based on fuzzy ranking
rankedItems := make([]completions.CompletionSuggestion, 0, len(matches))
for _, match := range matches {
rankedItems = append(rankedItems, allItems[match.OriginalIndex])
}
return rankedItems
return final
}
return allItems
// No query or no results: just concatenate in provider order
all := make([]completions.CompletionSuggestion, 0)
for _, entry := range itemsByProvider {
all = append(all, entry.items...)
}
return all
}
}
func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -131,10 +131,28 @@ func (s *SearchDialog) Init() tea.Cmd {
return textinput.Blink
}
func (s *SearchDialog) updateTextInput(msg tea.Msg) []tea.Cmd {
var cmds []tea.Cmd
oldValue := s.textInput.Value()
var cmd tea.Cmd
s.textInput, cmd = s.textInput.Update(msg)
if cmd != nil {
cmds = append(cmds, cmd)
}
if newValue := s.textInput.Value(); newValue != oldValue {
cmds = append(cmds, func() tea.Msg {
return SearchQueryChangedMsg{Query: newValue}
})
}
return cmds
}
func (s *SearchDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.PasteMsg, tea.ClipboardMsg:
cmds = append(cmds, s.updateTextInput(msg)...)
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
@@ -183,17 +201,7 @@ func (s *SearchDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
default:
oldValue := s.textInput.Value()
var cmd tea.Cmd
s.textInput, cmd = s.textInput.Update(msg)
if cmd != nil {
cmds = append(cmds, cmd)
}
if newValue := s.textInput.Value(); newValue != oldValue {
cmds = append(cmds, func() tea.Msg {
return SearchQueryChangedMsg{Query: newValue}
})
}
cmds = append(cmds, s.updateTextInput(msg)...)
}
}
@@ -121,7 +121,7 @@ func (m *statusComponent) View() string {
var modeBackground compat.AdaptiveColor
var modeForeground compat.AdaptiveColor
switch m.app.ModeIndex {
switch m.app.AgentIndex {
case 0:
modeBackground = t.BackgroundElement()
modeForeground = t.TextMuted()
@@ -148,31 +148,31 @@ func (m *statusComponent) View() string {
modeForeground = t.BackgroundPanel()
}
command := m.app.Commands[commands.SwitchModeCommand]
command := m.app.Commands[commands.SwitchAgentCommand]
kb := command.Keybindings[0]
key := kb.Key
if kb.RequiresLeader {
key = m.app.Config.Keybinds.Leader + " " + kb.Key
}
modeStyle := styles.NewStyle().Background(modeBackground).Foreground(modeForeground)
modeNameStyle := modeStyle.Bold(true).Render
modeDescStyle := modeStyle.Render
mode := modeNameStyle(strings.ToUpper(m.app.Mode.Name)) + modeDescStyle(" MODE")
mode = modeStyle.
agentStyle := styles.NewStyle().Background(modeBackground).Foreground(modeForeground)
agentNameStyle := agentStyle.Bold(true).Render
agentDescStyle := agentStyle.Render
agent := agentNameStyle(strings.ToUpper(m.app.Agent().Name)) + agentDescStyle(" AGENT")
agent = agentStyle.
Padding(0, 1).
BorderLeft(true).
BorderStyle(lipgloss.ThickBorder()).
BorderForeground(modeBackground).
BorderBackground(t.BackgroundPanel()).
Render(mode)
Render(agent)
faintStyle := styles.NewStyle().
Faint(true).
Background(t.BackgroundPanel()).
Foreground(t.TextMuted())
mode = faintStyle.Render(key+" ") + mode
modeWidth := lipgloss.Width(mode)
agent = faintStyle.Render(key+" ") + agent
modeWidth := lipgloss.Width(agent)
availableWidth := m.width - logoWidth - modeWidth
branchSuffix := ""
@@ -206,7 +206,7 @@ func (m *statusComponent) View() string {
View: logo + cwd,
},
layout.FlexItem{
View: mode,
View: agent,
},
)
+2
View File
@@ -285,6 +285,8 @@ func generateMarkdownStyleConfig(backgroundColor compat.AdaptiveColor) ansi.Styl
StyleBlock: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
BlockSuffix: "\n",
// TODO: find better way to fix markdown table renders
BackgroundColor: stringPtr(""),
},
},
CenterSeparator: stringPtr("┼"),
@@ -0,0 +1,219 @@
{
"$schema": "https://opencode.ai/theme.json",
"defs": {
"vesperBg": "#101010",
"vesperFg": "#FFF",
"vesperComment": "#8b8b8b94",
"vesperKeyword": "#A0A0A0",
"vesperFunction": "#FFC799",
"vesperString": "#99FFE4",
"vesperNumber": "#FFC799",
"vesperError": "#FF8080",
"vesperWarning": "#FFC799",
"vesperSuccess": "#99FFE4",
"vesperMuted": "#A0A0A0"
},
"theme": {
"primary": {
"dark": "#FFC799",
"light": "#FFC799"
},
"secondary": {
"dark": "#99FFE4",
"light": "#99FFE4"
},
"accent": {
"dark": "#FFC799",
"light": "#FFC799"
},
"error": {
"dark": "vesperError",
"light": "vesperError"
},
"warning": {
"dark": "vesperWarning",
"light": "vesperWarning"
},
"success": {
"dark": "vesperSuccess",
"light": "vesperSuccess"
},
"info": {
"dark": "#FFC799",
"light": "#FFC799"
},
"text": {
"dark": "vesperFg",
"light": "vesperBg"
},
"textMuted": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"background": {
"dark": "vesperBg",
"light": "#FFF"
},
"backgroundPanel": {
"dark": "vesperBg",
"light": "#F0F0F0"
},
"backgroundElement": {
"dark": "vesperBg",
"light": "#E0E0E0"
},
"border": {
"dark": "#282828",
"light": "#D0D0D0"
},
"borderActive": {
"dark": "#FFC799",
"light": "#FFC799"
},
"borderSubtle": {
"dark": "#1C1C1C",
"light": "#E8E8E8"
},
"diffAdded": {
"dark": "vesperSuccess",
"light": "vesperSuccess"
},
"diffRemoved": {
"dark": "vesperError",
"light": "vesperError"
},
"diffContext": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"diffHunkHeader": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"diffHighlightAdded": {
"dark": "vesperSuccess",
"light": "vesperSuccess"
},
"diffHighlightRemoved": {
"dark": "vesperError",
"light": "vesperError"
},
"diffAddedBg": {
"dark": "#0d2818",
"light": "#e8f5e8"
},
"diffRemovedBg": {
"dark": "#281a1a",
"light": "#f5e8e8"
},
"diffContextBg": {
"dark": "vesperBg",
"light": "#F8F8F8"
},
"diffLineNumber": {
"dark": "#505050",
"light": "#808080"
},
"diffAddedLineNumberBg": {
"dark": "#0d2818",
"light": "#e8f5e8"
},
"diffRemovedLineNumberBg": {
"dark": "#281a1a",
"light": "#f5e8e8"
},
"markdownText": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownHeading": {
"dark": "#FFC799",
"light": "#FFC799"
},
"markdownLink": {
"dark": "#FFC799",
"light": "#FFC799"
},
"markdownLinkText": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"markdownCode": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"markdownBlockQuote": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownEmph": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownStrong": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownHorizontalRule": {
"dark": "#65737E",
"light": "#65737E"
},
"markdownListItem": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownListEnumeration": {
"dark": "vesperFg",
"light": "vesperBg"
},
"markdownImage": {
"dark": "#FFC799",
"light": "#FFC799"
},
"markdownImageText": {
"dark": "vesperMuted",
"light": "vesperMuted"
},
"markdownCodeBlock": {
"dark": "vesperFg",
"light": "vesperBg"
},
"syntaxComment": {
"dark": "vesperComment",
"light": "vesperComment"
},
"syntaxKeyword": {
"dark": "vesperKeyword",
"light": "vesperKeyword"
},
"syntaxFunction": {
"dark": "vesperFunction",
"light": "vesperFunction"
},
"syntaxVariable": {
"dark": "vesperFg",
"light": "vesperBg"
},
"syntaxString": {
"dark": "vesperString",
"light": "vesperString"
},
"syntaxNumber": {
"dark": "vesperNumber",
"light": "vesperNumber"
},
"syntaxType": {
"dark": "vesperFunction",
"light": "vesperFunction"
},
"syntaxOperator": {
"dark": "vesperKeyword",
"light": "vesperKeyword"
},
"syntaxPunctuation": {
"dark": "vesperFg",
"light": "vesperBg"
}
}
}
+27 -13
View File
@@ -69,6 +69,7 @@ type Model struct {
commandProvider completions.CompletionProvider
fileProvider completions.CompletionProvider
symbolsProvider completions.CompletionProvider
agentsProvider completions.CompletionProvider
showCompletionDialog bool
leaderBinding *key.Binding
toastManager *toast.ToastManager
@@ -211,8 +212,8 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
a.editor = updated.(chat.EditorComponent)
cmds = append(cmds, cmd)
// Set both file and symbols providers for @ completion
a.completions = dialog.NewCompletionDialogComponent("@", a.fileProvider, a.symbolsProvider)
// Set file, symbols, and agents providers for @ completion
a.completions = dialog.NewCompletionDialogComponent("@", a.agentsProvider, a.fileProvider, a.symbolsProvider)
updated, cmd = a.completions.Update(msg)
a.completions = updated.(dialog.CompletionDialog)
cmds = append(cmds, cmd)
@@ -585,7 +586,7 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case app.ModelSelectedMsg:
a.app.Provider = &msg.Provider
a.app.Model = &msg.Model
a.app.State.ModeModel[a.app.Mode.Name] = app.ModeModel{
a.app.State.AgentModel[a.app.Agent().Name] = app.AgentModel{
ProviderID: msg.Provider.ID,
ModelID: msg.Model.ID,
}
@@ -612,6 +613,17 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
a.editor.SetExitKeyInDebounce(false)
case dialog.FindSelectedMsg:
return a.openFile(msg.FilePath)
case tea.PasteMsg, tea.ClipboardMsg:
// Paste events: prioritize modal if active, otherwise editor
if a.modal != nil {
updatedModal, cmd := a.modal.Update(msg)
a.modal = updatedModal.(layout.Modal)
return a, cmd
} else {
updatedEditor, cmd := a.editor.Update(msg)
a.editor = updatedEditor.(chat.EditorComponent)
return a, cmd
}
// API
case api.Request:
@@ -679,17 +691,17 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds = append(cmds, cmd)
a.status = s.(status.StatusComponent)
u, cmd := a.editor.Update(msg)
a.editor = u.(chat.EditorComponent)
updatedEditor, cmd := a.editor.Update(msg)
a.editor = updatedEditor.(chat.EditorComponent)
cmds = append(cmds, cmd)
u, cmd = a.messages.Update(msg)
a.messages = u.(chat.MessagesComponent)
updatedMessages, cmd := a.messages.Update(msg)
a.messages = updatedMessages.(chat.MessagesComponent)
cmds = append(cmds, cmd)
if a.modal != nil {
u, cmd := a.modal.Update(msg)
a.modal = u.(layout.Modal)
updatedModal, cmd := a.modal.Update(msg)
a.modal = updatedModal.(layout.Modal)
cmds = append(cmds, cmd)
}
@@ -940,12 +952,12 @@ func (a Model) executeCommand(command commands.Command) (tea.Model, tea.Cmd) {
case commands.AppHelpCommand:
helpDialog := dialog.NewHelpDialog(a.app)
a.modal = helpDialog
case commands.SwitchModeCommand:
updated, cmd := a.app.SwitchMode()
case commands.SwitchAgentCommand:
updated, cmd := a.app.SwitchAgent()
a.app = updated
cmds = append(cmds, cmd)
case commands.SwitchModeReverseCommand:
updated, cmd := a.app.SwitchModeReverse()
case commands.SwitchAgentReverseCommand:
updated, cmd := a.app.SwitchAgentReverse()
a.app = updated
cmds = append(cmds, cmd)
case commands.EditorOpenCommand:
@@ -1209,6 +1221,7 @@ func NewModel(app *app.App) tea.Model {
commandProvider := completions.NewCommandCompletionProvider(app)
fileProvider := completions.NewFileContextGroup(app)
symbolsProvider := completions.NewSymbolsContextGroup(app)
agentsProvider := completions.NewAgentsContextGroup(app)
messages := chat.NewMessagesComponent(app)
editor := chat.NewEditorComponent(app)
@@ -1229,6 +1242,7 @@ func NewModel(app *app.App) tea.Model {
commandProvider: commandProvider,
fileProvider: fileProvider,
symbolsProvider: symbolsProvider,
agentsProvider: agentsProvider,
leaderBinding: leaderBinding,
showCompletionDialog: false,
toastManager: toast.NewToastManager(),
-52
View File
@@ -1,52 +0,0 @@
package util
import (
"regexp"
"strings"
"github.com/charmbracelet/lipgloss/v2"
)
// PreventHyphenBreaks replaces regular hyphens with non-breaking hyphens to prevent
// sparse word breaks in hyphenated terms like "claude-code-action".
// This improves readability by keeping hyphenated words together.
// Only preserves hyphens within words, not markdown syntax like bullet points.
func PreventHyphenBreaks(text string) string {
// Use regex to match hyphens that are between word characters
// This preserves hyphens in words like "claude-code-action" but not in "- [ ]"
re := regexp.MustCompile(`(\w)-(\w)`)
return re.ReplaceAllString(text, "$1\u2011$2")
}
// RestoreHyphens converts non-breaking hyphens back to regular hyphens.
// This should be called after text processing (like word wrapping) is complete.
func RestoreHyphens(text string) string {
return strings.ReplaceAll(text, "\u2011", "-")
}
// ProcessTextWithHyphens applies hyphen preservation to text during processing.
// It wraps the provided processFunc with hyphen handling.
func ProcessTextWithHyphens(text string, processFunc func(string) string) string {
preserved := PreventHyphenBreaks(text)
processed := processFunc(preserved)
return RestoreHyphens(processed)
}
// GetMessageContainerFrame calculates the actual horizontal frame size
// (padding + borders) for message containers based on current theme.
func GetMessageContainerFrame() int {
style := lipgloss.NewStyle().
BorderStyle(lipgloss.ThickBorder()).
BorderLeft(true).
BorderRight(true).
PaddingLeft(2).
PaddingRight(2)
return style.GetHorizontalFrameSize()
}
// GetMarkdownContainerFrame calculates the actual horizontal frame size
// for markdown containers based on current theme.
func GetMarkdownContainerFrame() int {
// Markdown containers use the same styling as message containers
return GetMessageContainerFrame()
}
@@ -1,7 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/debian
{
"name": "Development",
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
"postCreateCommand": "go mod tidy"
}
-49
View File
@@ -1,49 +0,0 @@
name: CI
on:
push:
branches-ignore:
- 'generated'
- 'codegen/**'
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
- 'stl-preview-base/**'
jobs:
lint:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- name: Setup go
uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
- name: Run lints
run: ./scripts/lint
test:
timeout-minutes: 10
name: test
runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
- name: Setup go
uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
- name: Bootstrap
run: ./scripts/bootstrap
- name: Run tests
run: ./scripts/test

Some files were not shown because too many files have changed in this diff Show More