From c34aec060f2abb78486857b0e0d678cac52e2fab Mon Sep 17 00:00:00 2001 From: Dax Date: Thu, 7 Aug 2025 16:32:12 -0400 Subject: [PATCH] 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 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/ --- .opencode/agent/docs.md | 12 + .opencode/agent/example-driven-docs-writer.md | 44 --- bun.lock | 348 ++++++++++++++++++ packages/opencode/package.json | 7 + packages/opencode/src/agent/agent.ts | 34 +- packages/opencode/src/cli/cmd/github.ts | 2 +- packages/opencode/src/cli/cmd/run.ts | 32 +- packages/opencode/src/cli/cmd/tui.ts | 4 +- packages/opencode/src/config/config.ts | 53 ++- packages/opencode/src/index.ts | 5 +- packages/opencode/src/server/server.ts | 16 +- packages/opencode/src/session/index.ts | 54 ++- packages/opencode/src/session/message-v2.ts | 26 +- packages/opencode/src/session/mode.ts | 74 ---- packages/opencode/src/tool/task.ts | 16 +- packages/opencode/src/trace/index.ts | 58 +-- packages/sdk/go/.stats.yml | 6 +- packages/sdk/go/api.md | 7 +- packages/sdk/go/app.go | 140 ++++--- packages/sdk/go/app_test.go | 44 +-- packages/sdk/go/config.go | 306 ++++++++++++--- .../internal/requestconfig/requestconfig.go | 8 +- packages/sdk/go/session.go | 146 +++++++- packages/sdk/go/session_test.go | 2 +- packages/sdk/go/tui.go | 2 +- packages/sdk/stainless/stainless.yml | 6 +- packages/tui/cmd/opencode/main.go | 12 +- packages/tui/internal/app/app.go | 141 ++++--- packages/tui/internal/app/prompt.go | 99 ++--- packages/tui/internal/app/state.go | 26 +- .../tui/internal/attachment/attachment.go | 24 ++ packages/tui/internal/commands/command.go | 12 +- packages/tui/internal/completions/agents.go | 74 ++++ .../tui/internal/components/chat/editor.go | 25 ++ .../tui/internal/components/chat/message.go | 43 ++- .../tui/internal/components/chat/messages.go | 8 + .../internal/components/dialog/complete.go | 60 +-- .../tui/internal/components/status/status.go | 22 +- packages/tui/internal/tui/tui.go | 17 +- packages/web/src/content/docs/docs/agents.mdx | 337 +++++++++++++++-- .../web/src/content/docs/docs/keybinds.mdx | 2 +- packages/web/src/content/docs/docs/modes.mdx | 331 ----------------- 42 files changed, 1755 insertions(+), 930 deletions(-) create mode 100644 .opencode/agent/docs.md delete mode 100644 .opencode/agent/example-driven-docs-writer.md delete mode 100644 packages/opencode/src/session/mode.ts create mode 100644 packages/tui/internal/completions/agents.go delete mode 100644 packages/web/src/content/docs/docs/modes.mdx diff --git a/.opencode/agent/docs.md b/.opencode/agent/docs.md new file mode 100644 index 00000000..ca317e00 --- /dev/null +++ b/.opencode/agent/docs.md @@ -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. diff --git a/.opencode/agent/example-driven-docs-writer.md b/.opencode/agent/example-driven-docs-writer.md deleted file mode 100644 index fec57d05..00000000 --- a/.opencode/agent/example-driven-docs-writer.md +++ /dev/null @@ -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: - 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.' Since the user needs - documentation with examples, use the example-driven-docs-writer agent to - create comprehensive docs with code samples. - 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.' The user needs - documentation that demonstrates configuration options, perfect for the - example-driven-docs-writer agent. ---- -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. diff --git a/bun.lock b/bun.lock index 1229cc97..223401a4 100644 --- a/bun.lock +++ b/bun.lock @@ -45,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:", @@ -138,6 +145,7 @@ "trustedDependencies": [ "sharp", "esbuild", + "protobufjs", ], "catalog": { "@tsconfig/node22": "22.0.2", @@ -335,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=="], @@ -391,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=="], @@ -449,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=="], @@ -477,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=="], @@ -559,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=="], @@ -569,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=="], @@ -589,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=="], @@ -615,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=="], @@ -687,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=="], @@ -705,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=="], @@ -743,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=="], @@ -869,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=="], @@ -955,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=="], @@ -965,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=="], @@ -983,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=="], @@ -1041,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=="], @@ -1057,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=="], @@ -1065,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=="], @@ -1087,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=="], @@ -1107,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=="], @@ -1119,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=="], @@ -1133,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=="], @@ -1155,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=="], @@ -1317,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=="], @@ -1343,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=="], @@ -1385,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=="], @@ -1409,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=="], @@ -1433,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=="], @@ -1513,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=="], @@ -1623,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=="], @@ -1641,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=="], @@ -1649,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=="], @@ -1805,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=="], @@ -1871,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=="], @@ -1881,6 +2185,16 @@ "@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=="], @@ -1907,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=="], @@ -1915,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=="], @@ -1949,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=="], @@ -2011,6 +2331,20 @@ "@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=="], @@ -2091,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=="], } } diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 84432ba7..4a1ed555 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -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:", diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 263e0500..6fee2fdd 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -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 + const state = App.state("agent", async () => { const cfg = await Config.get() const result: Record = { @@ -35,6 +39,21 @@ 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 ?? {})) { @@ -46,14 +65,10 @@ export namespace Agent { 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 = { @@ -61,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 }) diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index f33cb3ec..a6f8917a 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -641,7 +641,7 @@ export const GithubRunCommand = cmd({ messageID: Identifier.ascending("message"), providerID, modelID, - mode: "build", + agent: "build", parts: [ { id: Identifier.ascending("part"), diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 98ed86bc..93194088 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -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 = { 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,8 +103,19 @@ export const RunCommand = cmd({ } UI.empty() - const mode = args.mode ? await Mode.get(args.mode) : await Mode.list().then((x) => x[0]) - const { providerID, modelID } = args.model ? Provider.parseModel(args.model) : mode.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() @@ -157,14 +168,17 @@ export const RunCommand = cmd({ UI.error(err) }) - const messageID = Identifier.ascending("message") const result = await Session.chat({ sessionID: session.id, messageID, - providerID, - modelID, - mode: mode.name, + ...(agent.model + ? agent.model + : { + providerID, + modelID, + }), + agent: agent.name, parts: [ { id: Identifier.ascending("part"), diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index 54cb1497..7a9c3065 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -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() diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 3a9ab972..c2491e8b 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -83,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, @@ -92,6 +92,15 @@ 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( @@ -108,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") @@ -149,7 +164,7 @@ export namespace Config { export const Mcp = z.discriminatedUnion("type", [McpLocal, McpRemote]) export type Mcp = z.infer - export const Mode = z + export const Agent = z .object({ model: z.string().optional(), temperature: z.number().optional(), @@ -157,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 - - export const Agent = Mode.extend({ - description: z.string(), - }).openapi({ - ref: "AgentConfig", - }) + export type Agent = z.infer export const Keybinds = z .object({ leader: z.string().optional().default("ctrl+x").describe("Leader key for keybind combinations"), app_help: z.string().optional().default("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("e").describe("Open external editor"), session_export: z.string().optional().default("x").describe("Export session to editor"), session_new: z.string().optional().default("n").describe("Create a new session"), @@ -257,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() diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 23d0e6bf..8ef14e57 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -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() diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 56af5ebb..60433248 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -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: { @@ -872,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) }, ) @@ -1027,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: { diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index c4d81a8c..d37528eb 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -36,12 +36,12 @@ 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" }) @@ -357,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( @@ -382,6 +382,16 @@ export namespace Session { .openapi({ ref: "FilePartInput", }), + MessageV2.AgentPart.omit({ + messageID: true, + sessionID: true, + }) + .partial({ + id: true, + }) + .openapi({ + ref: "AgentPartInput", + }), ]), ), }) @@ -393,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) @@ -566,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"), @@ -576,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, @@ -683,12 +715,12 @@ export namespace Session { .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) })(), ) @@ -702,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, @@ -727,7 +759,7 @@ export namespace Session { const processor = createProcessor(assistantMsg, model.info) const enabledTools = pipe( - mode.tools, + agent.tools, mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID)), mergeDeep(input.tools ?? {}), ) @@ -818,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", @@ -871,7 +903,7 @@ export namespace Session { }, modelID: input.modelID, providerID: input.providerID, - mode: inputMode, + mode: inputAgent, time: { created: Date.now(), }, diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 488f9e3c..f12526e7 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -172,6 +172,21 @@ export namespace MessageV2 { }) export type FilePart = z.infer + 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 + export const StepStartPart = PartBase.extend({ type: z.literal("step-start"), }).openapi({ @@ -212,7 +227,16 @@ export namespace MessageV2 { export type User = z.infer 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", }) diff --git a/packages/opencode/src/session/mode.ts b/packages/opencode/src/session/mode.ts deleted file mode 100644 index baf2ba24..00000000 --- a/packages/opencode/src/session/mode.ts +++ /dev/null @@ -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 - const state = App.state("mode", async () => { - const cfg = await Config.get() - const model = cfg.model ? Provider.parseModel(cfg.model) : undefined - const result: Record = { - 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)) - } -} diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 0ae0ef79..0b518b2b 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -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({ @@ -51,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: [ { diff --git a/packages/opencode/src/trace/index.ts b/packages/opencode/src/trace/index.ts index 8dba93d5..06b849d6 100644 --- a/packages/opencode/src/trace/index.ts +++ b/packages/opencode/src/trace/index.ts @@ -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() } } diff --git a/packages/sdk/go/.stats.yml b/packages/sdk/go/.stats.yml index 013bb9ac..a2023f0e 100644 --- a/packages/sdk/go/.stats.yml +++ b/packages/sdk/go/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 34 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-52fd0b61e84fdc1cdd31ec12e1600510e9dd2f9d4fb20c2315b4975cb763ee98.yml -openapi_spec_hash: e851b8d5a2412f5fc9be82ab88ebdfde -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 diff --git a/packages/sdk/go/api.md b/packages/sdk/go/api.md index 672460b9..d7195199 100644 --- a/packages/sdk/go/api.md +++ b/packages/sdk/go/api.md @@ -18,18 +18,18 @@ Methods: Response Types: +- opencode.Agent - opencode.App -- opencode.Mode - opencode.Model - opencode.Provider - opencode.AppProvidersResponse Methods: +- client.App.Agents(ctx context.Context) ([]opencode.Agent, error) - client.App.Get(ctx context.Context) (opencode.App, error) - client.App.Init(ctx context.Context) (bool, error) - client.App.Log(ctx context.Context, body opencode.AppLogParams) (bool, error) -- client.App.Modes(ctx context.Context) ([]opencode.Mode, error) - client.App.Providers(ctx context.Context) (opencode.AppProvidersResponse, error) # Find @@ -65,7 +65,6 @@ Response Types: - opencode.KeybindsConfig - opencode.McpLocalConfig - opencode.McpRemoteConfig -- opencode.ModeConfig Methods: @@ -75,6 +74,7 @@ Methods: Params Types: +- opencode.AgentPartInputParam - opencode.FilePartInputParam - opencode.FilePartSourceUnionParam - opencode.FilePartSourceTextParam @@ -84,6 +84,7 @@ Params Types: Response Types: +- opencode.AgentPart - opencode.AssistantMessage - opencode.FilePart - opencode.FilePartSource diff --git a/packages/sdk/go/app.go b/packages/sdk/go/app.go index 0a7d14e7..3a0161a1 100644 --- a/packages/sdk/go/app.go +++ b/packages/sdk/go/app.go @@ -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,58 +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"` - TopP float64 `json:"topP"` - 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 - TopP 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"` diff --git a/packages/sdk/go/app_test.go b/packages/sdk/go/app_test.go index 16bb8ff8..2ade6c7e 100644 --- a/packages/sdk/go/app_test.go +++ b/packages/sdk/go/app_test.go @@ -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" diff --git a/packages/sdk/go/config.go b/packages/sdk/go/config.go index 911bb2a3..a7b75a1b 100644 --- a/packages/sdk/go/config.go +++ b/packages/sdk/go/config.go @@ -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 @@ -63,7 +63,7 @@ type Config struct { 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"` @@ -119,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 } @@ -141,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 } @@ -163,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:"-"` @@ -516,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:"-"` } @@ -540,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"` @@ -588,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 @@ -609,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 @@ -624,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 @@ -866,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"` @@ -913,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 @@ -1022,33 +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"` - TopP float64 `json:"top_p"` - 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 - TopP 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 -} diff --git a/packages/sdk/go/internal/requestconfig/requestconfig.go b/packages/sdk/go/internal/requestconfig/requestconfig.go index 91b70cca..53bf9f58 100644 --- a/packages/sdk/go/internal/requestconfig/requestconfig.go +++ b/packages/sdk/go/internal/requestconfig/requestconfig.go @@ -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) diff --git a/packages/sdk/go/session.go b/packages/sdk/go/session.go index d38c37e0..bae17cf2 100644 --- a/packages/sdk/go/session.go +++ b/packages/sdk/go/session.go @@ -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 diff --git a/packages/sdk/go/session_test.go b/packages/sdk/go/session_test.go index ab9fbcf7..b8158f09 100644 --- a/packages/sdk/go/session_test.go +++ b/packages/sdk/go/session_test.go @@ -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, diff --git a/packages/sdk/go/tui.go b/packages/sdk/go/tui.go index 30657890..986b73aa 100644 --- a/packages/sdk/go/tui.go +++ b/packages/sdk/go/tui.go @@ -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" diff --git a/packages/sdk/stainless/stainless.yml b/packages/sdk/stainless/stainless.yml index b9d69cde..3a8da406 100644 --- a/packages/sdk/stainless/stainless.yml +++ b/packages/sdk/stainless/stainless.yml @@ -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 diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go index 5532289f..654eb0ad 100644 --- a/packages/tui/cmd/opencode/main.go +++ b/packages/tui/cmd/opencode/main.go @@ -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) } diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go index a0e68b53..9794d048 100644 --- a/packages/tui/internal/app/app.go +++ b/packages/tui/internal/app/app.go @@ -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()), }) diff --git a/packages/tui/internal/app/prompt.go b/packages/tui/internal/app/prompt.go index 282ced70..81c4b6a7 100644 --- a/packages/tui/internal/app/prompt.go +++ b/packages/tui/internal/app/prompt.go @@ -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 -} diff --git a/packages/tui/internal/app/state.go b/packages/tui/internal/app/state.go index bf2a602b..47802235 100644 --- a/packages/tui/internal/app/state.go +++ b/packages/tui/internal/app/state.go @@ -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), } diff --git a/packages/tui/internal/attachment/attachment.go b/packages/tui/internal/attachment/attachment.go index 038209ae..3ecd8619 100644 --- a/packages/tui/internal/attachment/attachment.go +++ b/packages/tui/internal/attachment/attachment.go @@ -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 } } } diff --git a/packages/tui/internal/commands/command.go b/packages/tui/internal/commands/command.go index f8779479..cb54bd09 100644 --- a/packages/tui/internal/commands/command.go +++ b/packages/tui/internal/commands/command.go @@ -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"), }, { diff --git a/packages/tui/internal/completions/agents.go b/packages/tui/internal/completions/agents.go new file mode 100644 index 00000000..cda2be88 --- /dev/null +++ b/packages/tui/internal/completions/agents.go @@ -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, + } +} diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go index 1263a6e7..509de624 100644 --- a/packages/tui/internal/components/chat/editor.go +++ b/packages/tui/internal/components/chat/editor.go @@ -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 diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go index 0a198271..60d0fab5 100644 --- a/packages/tui/internal/components/chat/message.go +++ b/packages/tui/internal/components/chat/message.go @@ -209,6 +209,7 @@ func renderText( width int, extra string, fileParts []opencode.FilePart, + agentParts []opencode.AgentPart, toolCalls ...opencode.ToolPart, ) string { t := theme.CurrentTheme() @@ -229,9 +230,47 @@ func renderText( // 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 diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go index 5702cec5..46036b75 100644 --- a/packages/tui/internal/components/chat/messages.go +++ b/packages/tui/internal/components/chat/messages.go @@ -300,12 +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: 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{} @@ -355,6 +360,7 @@ func (m *messagesComponent) renderView() tea.Cmd { width, files, fileParts, + agentParts, ) content = lipgloss.PlaceHorizontal( m.width, @@ -433,6 +439,7 @@ func (m *messagesComponent) renderView() tea.Cmd { width, "", []opencode.FilePart{}, + []opencode.AgentPart{}, toolCallParts..., ) content = lipgloss.PlaceHorizontal( @@ -453,6 +460,7 @@ func (m *messagesComponent) renderView() tea.Cmd { width, "", []opencode.FilePart{}, + []opencode.AgentPart{}, toolCallParts..., ) content = lipgloss.PlaceHorizontal( diff --git a/packages/tui/internal/components/dialog/complete.go b/packages/tui/internal/components/dialog/complete.go index f18d9751..d3d2ea9d 100644 --- a/packages/tui/internal/components/dialog/complete.go +++ b/packages/tui/internal/components/dialog/complete.go @@ -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) { diff --git a/packages/tui/internal/components/status/status.go b/packages/tui/internal/components/status/status.go index d57c228c..be34dd93 100644 --- a/packages/tui/internal/components/status/status.go +++ b/packages/tui/internal/components/status/status.go @@ -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, }, ) diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 7f5b4871..22e8afdb 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -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, } @@ -951,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: @@ -1220,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) @@ -1240,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(), diff --git a/packages/web/src/content/docs/docs/agents.mdx b/packages/web/src/content/docs/docs/agents.mdx index 6760abaa..950f910f 100644 --- a/packages/web/src/content/docs/docs/agents.mdx +++ b/packages/web/src/content/docs/docs/agents.mdx @@ -5,6 +5,52 @@ description: Configure and use specialized agents in opencode. Agents are specialized AI assistants that can be configured for specific tasks and workflows. They allow you to create focused tools with custom prompts, models, and tool access. +:::tip +Use the plan agent to analyze code and review suggestions without making any code changes. +::: + +You can switch between agents during a session or configure them in your config file. + +--- + +## Agent Types + +opencode has two types of agents: + +### Primary Agents + +Primary agents are the main assistants you interact with directly. You can cycle through them using the **Tab** key (or your configured `switch_agent` keybind). These agents handle your main conversation and can access all configured tools. + +**Built-in Primary Agents:** + +- **Build** - The default agent with all tools enabled. Standard for development work where you need full access to file operations and system commands. +- **Plan** - A restricted agent for planning and analysis. Has `write`, `edit`, `patch`, and `bash` tools disabled by default. Useful for analyzing code and suggesting changes without making modifications. + +### Subagents + +Subagents are specialized assistants that primary agents can invoke for specific tasks. You can also manually invoke them by **@ mentioning** them in your messages (e.g., `@general help me search for this function`). + +**Built-in Subagents:** + +- **General** - General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. Use when searching for keywords or files and you're not confident you'll find the right match in the first few tries. + +--- + +## Using Agents + +### Switching Primary Agents + +Use the **Tab** key to cycle through available primary agents during a session. You can also use your configured `switch_agent` keybind. + +### Invoking Subagents + +- **Automatic**: Primary agents will automatically use subagents for specialized tasks based on their descriptions +- **Manual**: @ mention a subagent in your message: `@general search for authentication code` + +See also: [Formatters](/docs/formatters) for information about code formatting configuration. + +--- + ## Creating Agents You can create new agents using the `opencode agent create` command. This interactive command will: @@ -21,39 +67,46 @@ opencode agent create The command will guide you through the process and automatically generate a well-structured agent based on your requirements. -## Built-in Agents - -opencode comes with a built-in `general` agent: - -- **general** - General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. Use this when searching for keywords or files and you're not confident you'll find the right match in the first few tries. - ## Configuration -Agents can be configured in your `opencode.json` config file or as markdown files. +You can customize the built-in agents or create your own through configuration. Agents can be configured in two ways: ### JSON Configuration +Configure agents in your `opencode.json` config file: + ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", "agent": { + "build": { + "mode": "primary", + "model": "anthropic/claude-sonnet-4-20250514", + "prompt": "{file:./prompts/build.txt}", + "tools": { + "write": true, + "edit": true, + "bash": true + } + }, + "plan": { + "mode": "primary", + "model": "anthropic/claude-haiku-4-20250514", + "tools": { + "write": false, + "edit": false, + "bash": false + } + }, "code-reviewer": { "description": "Reviews code for best practices and potential issues", + "mode": "subagent", "model": "anthropic/claude-sonnet-4-20250514", "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", "tools": { "write": false, "edit": false } - }, - "test-writer": { - "description": "Specialized agent for writing comprehensive tests", - "prompt": "You are a test writing specialist. Write thorough, maintainable tests.", - "tools": { - "bash": true, - "read": true, - "write": true - } } } } @@ -66,25 +119,113 @@ You can also define agents using markdown files. Place them in: - Global: `~/.config/opencode/agent/` - Project: `.opencode/agent/` -```markdown title="~/.config/opencode/agent/code-reviewer.md" +```markdown title="~/.config/opencode/agent/review.md" --- -description: Reviews code for best practices and potential issues +description: Reviews code for quality and best practices +mode: subagent model: anthropic/claude-sonnet-4-20250514 +temperature: 0.1 tools: write: false edit: false + bash: false --- -You are a code reviewer with expertise in security, performance, and maintainability. +You are in code review mode. Focus on: -Focus on: +- Code quality and best practices +- Potential bugs and edge cases +- Performance implications +- Security considerations -- Security vulnerabilities -- Performance bottlenecks -- Code maintainability -- Best practices adherence +Provide constructive feedback without making direct changes. ``` +The markdown file name becomes the agent name (e.g., `review.md` creates a `review` agent). + +Let's look at these configuration options in detail. + +--- + +### Model + +Use the `model` config to override the default model for this agent. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + +### Temperature + +Control the randomness and creativity of the AI's responses with the `temperature` config. Lower values make responses more focused and deterministic, while higher values increase creativity and variability. + +```json title="opencode.json" +{ + "agent": { + "plan": { + "temperature": 0.1 + }, + "creative": { + "temperature": 0.8 + } + } +} +``` + +Temperature values typically range from 0.0 to 1.0: + +- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning +- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks +- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration + +```json title="opencode.json" +{ + "agent": { + "analyze": { + "temperature": 0.1, + "prompt": "{file:./prompts/analysis.txt}" + }, + "build": { + "temperature": 0.3 + }, + "brainstorm": { + "temperature": 0.7, + "prompt": "{file:./prompts/creative.txt}" + } + } +} +``` + +If no temperature is specified, opencode uses model-specific defaults (typically 0 for most models, 0.55 for Qwen models). + +--- + +### Prompt + +Specify a custom system prompt file for this agent with the `prompt` config. The prompt file should contain instructions specific to the agent's purpose. + +```json title="opencode.json" +{ + "agent": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +This path is relative to where the config file is located. So this works for both the global opencode config and the project specific config. + +--- + ## Agent Properties ### Required @@ -96,39 +237,66 @@ Focus on: - **model** - Specific model to use (defaults to your configured model) - **prompt** - Custom system prompt for the agent - **tools** - Object specifying which tools the agent can access (true/false for each tool) +- **temperature** - Control response randomness (0.0-1.0) +- **mode** - Agent type: `"primary"` (can be cycled with Tab), `"subagent"` (invoked by @ mention), or `"all"` (both) - **disable** - Set to true to disable the agent -## Tool Access +### Tools -By default, agents inherit the same tool access as the main assistant. You can restrict or enable specific tools: +Control which tools are available in this agent with the `tools` config. You can enable or disable specific tools by setting them to `true` or `false`. ```json { "agent": { - "readonly-agent": { - "description": "Read-only agent for analysis", + "readonly": { "tools": { "write": false, "edit": false, - "bash": false + "bash": false, + "read": true, + "grep": true, + "glob": true } } } } ``` -Common tools you might want to control: +If no tools are specified, all tools are enabled by default. -- `write` - Create new files -- `edit` - Modify existing files -- `bash` - Execute shell commands -- `read` - Read files -- `glob` - Search for files -- `grep` - Search file contents +--- -## Using Agents +#### Available tools -Agents are automatically available through the Task tool when configured. The main assistant will use them for specialized tasks based on their descriptions. +Here are all the tools can be controlled through the agent config. + +| Tool | Description | +| ----------- | ----------------------- | +| `bash` | Execute shell commands | +| `edit` | Modify existing files | +| `write` | Create new files | +| `read` | Read file contents | +| `grep` | Search file contents | +| `glob` | Find files by pattern | +| `list` | List directory contents | +| `patch` | Apply patches to files | +| `todowrite` | Manage todo lists | +| `todoread` | Read todo lists | +| `webfetch` | Fetch web content | + +--- + +## Tool Access + +By default, agents inherit the same tool access as the main assistant. You can restrict or enable specific tools as shown in the Tools section above. + +## Agent Modes + +The `mode` property determines how an agent can be used: + +- **`"primary"`** - Can be cycled through with Tab key as your main assistant +- **`"subagent"`** - Can be invoked by @ mentioning or automatically by primary agents +- **`"all"`** - Can be used both as primary and subagent (default for custom agents) ## Best Practices @@ -138,6 +306,97 @@ Agents are automatically available through the Task tool when configured. The ma 4. **Consistent naming** - Use descriptive, consistent names for your agents 5. **Project-specific agents** - Use `.opencode/agent/` for project-specific workflows +## Custom Agents + +You can create your own custom agents by adding them to the configuration. Here are examples using both approaches: + +### Using JSON configuration + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "agent": { + "docs": { + "prompt": "{file:./prompts/documentation.txt}", + "tools": { + "write": true, + "edit": true, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +### Using markdown files + +Create agent files in `.opencode/agent/` for project-specific agents or `~/.config/opencode/agent/` for global agents: + +```markdown title=".opencode/agent/debug.md" +--- +temperature: 0.1 +tools: + bash: true + read: true + grep: true + write: false + edit: false +--- + +You are in debug mode. Your primary goal is to help investigate and diagnose issues. + +Focus on: + +- Understanding the problem through careful analysis +- Using bash commands to inspect system state +- Reading relevant files and logs +- Searching for patterns and anomalies +- Providing clear explanations of findings + +Do not make any changes to files. Only investigate and report. +``` + +```markdown title="~/.config/opencode/agent/refactor.md" +--- +model: anthropic/claude-sonnet-4-20250514 +temperature: 0.2 +tools: + edit: true + read: true + grep: true + glob: true +--- + +You are in refactoring mode. Focus on improving code quality without changing functionality. + +Priorities: + +- Improve code readability and maintainability +- Apply consistent naming conventions +- Reduce code duplication +- Optimize performance where appropriate +- Ensure all tests continue to pass +``` + +--- + +### Use cases + +Here are some common use cases for different agents. + +- **Build agent**: Full development work with all tools enabled +- **Plan agent**: Analysis and planning without making changes +- **Review agent**: Code review with read-only access plus documentation tools +- **Debug agent**: Focused on investigation with bash and read tools enabled +- **Docs agent**: Documentation writing with file operations but no system commands + +You might also find different models are good for different use cases. + +--- + ## Examples ### Documentation Agent @@ -145,6 +404,7 @@ Agents are automatically available through the Task tool when configured. The ma ```markdown title="~/.config/opencode/agent/docs-writer.md" --- description: Writes and maintains project documentation +mode: subagent tools: bash: false --- @@ -164,6 +424,7 @@ Focus on: ```markdown title="~/.config/opencode/agent/security-auditor.md" --- description: Performs security audits and identifies vulnerabilities +mode: subagent tools: write: false edit: false diff --git a/packages/web/src/content/docs/docs/keybinds.mdx b/packages/web/src/content/docs/docs/keybinds.mdx index 076b428f..6bb573bc 100644 --- a/packages/web/src/content/docs/docs/keybinds.mdx +++ b/packages/web/src/content/docs/docs/keybinds.mdx @@ -11,7 +11,7 @@ opencode has a list of keybinds that you can customize through the opencode conf "keybinds": { "leader": "ctrl+x", "app_help": "h", - "switch_mode": "tab", + "switch_agent": "tab", "editor_open": "e", diff --git a/packages/web/src/content/docs/docs/modes.mdx b/packages/web/src/content/docs/docs/modes.mdx deleted file mode 100644 index 133fe7bd..00000000 --- a/packages/web/src/content/docs/docs/modes.mdx +++ /dev/null @@ -1,331 +0,0 @@ ---- -title: Modes -description: Different modes for different use cases. ---- - -Modes in opencode allow you to customize the behavior, tools, and prompts for different use cases. - -It comes with two built-in modes: **build** and **plan**. You can customize -these or configure your own through the opencode config. - -:::tip -Use the plan mode to analyze code and review suggestions without making any code -changes. -::: - -You can switch between modes during a session or configure them in your config file. - ---- - -## Built-in - -opencode comes with two built-in modes. - ---- - -### Build - -Build is the **default** mode with all tools enabled. This is the standard mode for development work where you need full access to file operations and system commands. - ---- - -### Plan - -A restricted mode designed for planning and analysis. In plan mode, the following tools are disabled by default: - -- `write` - Cannot create new files -- `edit` - Cannot modify existing files -- `patch` - Cannot apply patches -- `bash` - Cannot execute shell commands - -This mode is useful when you want the AI to analyze code, suggest changes, or create plans without making any actual modifications to your codebase. - ---- - -## Switching - -You can switch between modes during a session using the _Tab_ key. Or your configured `switch_mode` keybind. - -See also: [Formatters](/docs/formatters) for information about code formatting configuration. - ---- - -## Configure - -You can customize the built-in modes or create your own through configuration. Modes can be configured in two ways: - -### JSON Configuration - -Configure modes in your `opencode.json` config file: - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mode": { - "build": { - "model": "anthropic/claude-sonnet-4-20250514", - "prompt": "{file:./prompts/build.txt}", - "tools": { - "write": true, - "edit": true, - "bash": true - } - }, - "plan": { - "model": "anthropic/claude-haiku-4-20250514", - "tools": { - "write": false, - "edit": false, - "bash": false - } - } - } -} -``` - -### Markdown Configuration - -You can also define modes using markdown files. Place them in: - -- Global: `~/.config/opencode/mode/` -- Project: `.opencode/mode/` - -```markdown title="~/.config/opencode/mode/review.md" ---- -model: anthropic/claude-sonnet-4-20250514 -temperature: 0.1 -tools: - write: false - edit: false - bash: false ---- - -You are in code review mode. Focus on: - -- Code quality and best practices -- Potential bugs and edge cases -- Performance implications -- Security considerations - -Provide constructive feedback without making direct changes. -``` - -The markdown file name becomes the mode name (e.g., `review.md` creates a `review` mode). - -Let's look at these configuration options in detail. - ---- - -### Model - -Use the `model` config to override the default model for this mode. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation. - -```json title="opencode.json" -{ - "mode": { - "plan": { - "model": "anthropic/claude-haiku-4-20250514" - } - } -} -``` - ---- - -### Temperature - -Control the randomness and creativity of the AI's responses with the `temperature` config. Lower values make responses more focused and deterministic, while higher values increase creativity and variability. - -```json title="opencode.json" -{ - "mode": { - "plan": { - "temperature": 0.1 - }, - "creative": { - "temperature": 0.8 - } - } -} -``` - -Temperature values typically range from 0.0 to 1.0: - -- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning -- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks -- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration - -```json title="opencode.json" -{ - "mode": { - "analyze": { - "temperature": 0.1, - "prompt": "{file:./prompts/analysis.txt}" - }, - "build": { - "temperature": 0.3 - }, - "brainstorm": { - "temperature": 0.7, - "prompt": "{file:./prompts/creative.txt}" - } - } -} -``` - -If no temperature is specified, opencode uses model-specific defaults (typically 0 for most models, 0.55 for Qwen models). - ---- - -### Prompt - -Specify a custom system prompt file for this mode with the `prompt` config. The prompt file should contain instructions specific to the mode's purpose. - -```json title="opencode.json" -{ - "mode": { - "review": { - "prompt": "{file:./prompts/code-review.txt}" - } - } -} -``` - -This path is relative to where the config file is located. So this works for -both the global opencode config and the project specific config. - ---- - -### Tools - -Control which tools are available in this mode with the `tools` config. You can enable or disable specific tools by setting them to `true` or `false`. - -```json -{ - "mode": { - "readonly": { - "tools": { - "write": false, - "edit": false, - "bash": false, - "read": true, - "grep": true, - "glob": true - } - } - } -} -``` - -If no tools are specified, all tools are enabled by default. - ---- - -#### Available tools - -Here are all the tools can be controlled through the mode config. - -| Tool | Description | -| ----------- | ----------------------- | -| `bash` | Execute shell commands | -| `edit` | Modify existing files | -| `write` | Create new files | -| `read` | Read file contents | -| `grep` | Search file contents | -| `glob` | Find files by pattern | -| `list` | List directory contents | -| `patch` | Apply patches to files | -| `todowrite` | Manage todo lists | -| `todoread` | Read todo lists | -| `webfetch` | Fetch web content | - ---- - -## Custom modes - -You can create your own custom modes by adding them to the configuration. Here are examples using both approaches: - -### Using JSON configuration - -```json title="opencode.json" {4-14} -{ - "$schema": "https://opencode.ai/config.json", - "mode": { - "docs": { - "prompt": "{file:./prompts/documentation.txt}", - "tools": { - "write": true, - "edit": true, - "bash": false, - "read": true, - "grep": true, - "glob": true - } - } - } -} -``` - -### Using markdown files - -Create mode files in `.opencode/mode/` for project-specific modes or `~/.config/opencode/mode/` for global modes: - -```markdown title=".opencode/mode/debug.md" ---- -temperature: 0.1 -tools: - bash: true - read: true - grep: true - write: false - edit: false ---- - -You are in debug mode. Your primary goal is to help investigate and diagnose issues. - -Focus on: - -- Understanding the problem through careful analysis -- Using bash commands to inspect system state -- Reading relevant files and logs -- Searching for patterns and anomalies -- Providing clear explanations of findings - -Do not make any changes to files. Only investigate and report. -``` - -```markdown title="~/.config/opencode/mode/refactor.md" ---- -model: anthropic/claude-sonnet-4-20250514 -temperature: 0.2 -tools: - edit: true - read: true - grep: true - glob: true ---- - -You are in refactoring mode. Focus on improving code quality without changing functionality. - -Priorities: - -- Improve code readability and maintainability -- Apply consistent naming conventions -- Reduce code duplication -- Optimize performance where appropriate -- Ensure all tests continue to pass -``` - ---- - -### Use cases - -Here are some common use cases for different modes. - -- **Build mode**: Full development work with all tools enabled -- **Plan mode**: Analysis and planning without making changes -- **Review mode**: Code review with read-only access plus documentation tools -- **Debug mode**: Focused on investigation with bash and read tools enabled -- **Docs mode**: Documentation writing with file operations but no system commands - -You might also find different models are good for different use cases.