From d9b81d2233a5c70f52ae1fbcd4cccef2ea57c7b1 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 17 Aug 2026 17:54:08 -0400 Subject: [PATCH] chore(effect): update to beta.107 (#43109) --- bun.lock | 42 +- package.json | 12 +- packages/ai/src/protocols/shared.ts | 5 +- packages/ai/src/provider-error.ts | 2 +- packages/ai/src/schema/errors.ts | 2 +- .../ai/test/provider/bedrock-mantle.test.ts | 1 - packages/ai/test/schema.test.ts | 13 +- packages/app/src/utils/session-message.ts | 2 +- packages/cli/src/acp/error.ts | 16 +- packages/client/package.json | 2 +- .../src/effect/generated/client-error.ts | 2 +- .../client/src/promise/generated/types.ts | 1578 +++++++++-------- packages/codemode/src/openapi/runtime.ts | 2 +- packages/codemode/src/tool-error.ts | 2 +- packages/codemode/test/codemode.test.ts | 2 +- packages/codemode/test/signature.test.ts | 6 +- packages/core/src/aisdk.ts | 6 +- packages/core/src/bus.ts | 2 +- packages/core/src/command.ts | 4 +- packages/core/src/config.ts | 2 +- ...0260805200742_import_legacy_credentials.ts | 2 +- .../core/src/database/v1-migration.bun.ts | 2 +- packages/core/src/environment/files.ts | 6 +- packages/core/src/form.ts | 10 +- packages/core/src/generate.ts | 4 +- packages/core/src/git.ts | 4 +- packages/core/src/image.ts | 6 +- packages/core/src/instructions/index.ts | 4 +- packages/core/src/integration.ts | 4 +- packages/core/src/mcp/client.ts | 4 +- packages/core/src/mcp/index.ts | 4 +- packages/core/src/model-resolver.ts | 6 +- packages/core/src/permission.ts | 8 +- .../plugin/provider/cloudflare-ai-gateway.ts | 2 +- .../src/plugin/provider/github-copilot.ts | 2 +- packages/core/src/provider.ts | 2 +- packages/core/src/pty.ts | 4 +- packages/core/src/repository-cache.ts | 14 +- packages/core/src/repository.ts | 6 +- packages/core/src/ripgrep.ts | 6 +- packages/core/src/schema.ts | 2 +- packages/core/src/session.ts | 18 +- packages/core/src/session/error.ts | 12 +- packages/core/src/session/inbox.ts | 2 +- packages/core/src/session/revert.ts | 2 +- packages/core/src/session/runner/model.ts | 4 +- .../core/src/session/runner/to-llm-message.ts | 2 +- packages/core/src/session/transfer.ts | 2 +- packages/core/src/shell.ts | 2 +- packages/core/src/snapshot.ts | 2 +- packages/core/src/tool.ts | 13 +- packages/core/src/tool/plugin/question.ts | 2 +- packages/core/src/tool/read-filesystem.ts | 8 +- packages/core/src/util/process-lock.ts | 4 +- packages/core/src/v1/permission.ts | 8 +- packages/core/src/websearch.ts | 8 +- packages/core/src/workspace.ts | 2 +- packages/core/src/workspace/driver.ts | 4 +- packages/core/src/worktree.ts | 10 +- packages/core/src/worktree/directory.ts | 2 +- packages/core/test/config/config.test.ts | 6 +- .../core/test/config/normalization.test.ts | 2 +- .../test/session-runner-tool-registry.test.ts | 6 +- packages/http-recorder/README.md | 6 +- packages/http-recorder/package.json | 2 +- packages/http-recorder/src/cassette/store.ts | 6 +- .../http-recorder/src/redaction/redactor.ts | 2 +- .../http-recorder/src/replay/comparison.ts | 2 +- packages/httpapi-codegen/src/index.ts | 238 ++- packages/httpapi-codegen/test/fixture.ts | 2 +- .../httpapi-codegen/test/generate.test.ts | 83 +- .../test/generated/client-error.ts | 2 +- .../httpapi-codegen/test/generated/session.ts | 2 +- packages/protocol/src/errors.ts | 44 +- packages/protocol/src/groups/worktree.ts | 2 +- packages/protocol/src/simulation.ts | 8 +- packages/schema/src/instruction-entry.ts | 2 +- packages/schema/src/tool.ts | 2 +- packages/server/src/event-feed.ts | 4 +- .../src/backend/simulated-provider.ts | 10 +- packages/simulation/src/manifest.ts | 2 +- packages/theme/src/tui/resolve.ts | 2 +- packages/tui/src/theme/index.ts | 2 +- packages/util/src/effect-flock.ts | 8 +- packages/util/src/fs-util.ts | 2 +- packages/util/src/npm.ts | 2 +- packages/util/src/observability.ts | 3 +- packages/util/src/patch.ts | 4 +- packages/util/src/process.ts | 2 +- patches/drizzle-orm@1.0.0-rc.2.patch | 42 + patches/effect@4.0.0-beta.101.patch | 37 - 91 files changed, 1332 insertions(+), 1117 deletions(-) create mode 100644 patches/drizzle-orm@1.0.0-rc.2.patch delete mode 100644 patches/effect@4.0.0-beta.101.patch diff --git a/bun.lock b/bun.lock index c1029b4567..4ba724139e 100644 --- a/bun.lock +++ b/bun.lock @@ -191,7 +191,7 @@ "solid-js": "catalog:", }, "peerDependencies": { - "effect": "4.0.0-beta.101", + "effect": "4.0.0-beta.107", "solid-js": ">=1.9.0", }, "optionalPeers": [ @@ -520,7 +520,7 @@ "name": "@opencode-ai/http-recorder", "version": "1.18.15", "dependencies": { - "@effect/platform-node-shared": "4.0.0-beta.101", + "@effect/platform-node-shared": "4.0.0-beta.107", }, "devDependencies": { "@effect/platform-node": "catalog:", @@ -1053,9 +1053,9 @@ ], "patchedDependencies": { "@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch", - "effect@4.0.0-beta.101": "patches/effect@4.0.0-beta.101.patch", - "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", "@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch", + "drizzle-orm@1.0.0-rc.2": "patches/drizzle-orm@1.0.0-rc.2.patch", + "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "@ai-sdk/mistral@3.0.51": "patches/@ai-sdk%2Fmistral@3.0.51.patch", "@ff-labs/fff-bun@0.10.1": "patches/@ff-labs%2Ffff-bun@0.10.1.patch", @@ -1067,6 +1067,7 @@ "@ai-sdk/openai-compatible@2.0.41": "patches/@ai-sdk%2Fopenai-compatible@2.0.41.patch", }, "overrides": { + "@effect/platform-node-shared": "catalog:", "@opentui/core": "catalog:", "@opentui/keymap": "catalog:", "@opentui/solid": "catalog:", @@ -1077,9 +1078,10 @@ "catalog": { "@cloudflare/workers-types": "4.20251008.0", "@corvu/drawer": "0.2.4", - "@effect/opentelemetry": "4.0.0-beta.101", - "@effect/platform-node": "4.0.0-beta.101", - "@effect/sql-sqlite-bun": "4.0.0-beta.101", + "@effect/opentelemetry": "4.0.0-beta.107", + "@effect/platform-node": "4.0.0-beta.107", + "@effect/platform-node-shared": "4.0.0-beta.107", + "@effect/sql-sqlite-bun": "4.0.0-beta.107", "@hono/standard-validator": "0.2.0", "@hono/zod-validator": "0.4.2", "@kobalte/core": "0.13.11", @@ -1116,7 +1118,7 @@ "dompurify": "3.3.1", "drizzle-kit": "1.0.0-rc.2", "drizzle-orm": "1.0.0-rc.2", - "effect": "4.0.0-beta.101", + "effect": "4.0.0-beta.107", "fuzzysort": "3.1.0", "get-east-asian-width": "1.6.0", "hono": "4.10.7", @@ -1563,13 +1565,13 @@ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], - "@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.101", "", { "peerDependencies": { "@opentelemetry/api": "^1.9", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^4.0.0-beta.101" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-IdejlqRLbjRHJgVnea4s8CxTWfvkSjM0HlnpNfP07IGTbhmAvPs7PMaWt1xzYWbOnI7CriQwxv+54eW1PwIkZg=="], + "@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.107", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-beta.107" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-WxR3OEcwVtckNYGxvERA4kiS8cb2B46lSWxQw8P6dCCzW0j0VC7hkWyzryJ16MVXfI/5xQHS3r5j9mud+JVvsg=="], - "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.101", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.101", "mime": "^4.1.0", "undici": "^8.7.0" }, "peerDependencies": { "effect": "^4.0.0-beta.101", "ioredis": "^5.7.0" } }, "sha512-pClk7dmMtHgM6Byu7CzGfrPvZ1/4BwmrRlCg2Op+iJozMkwVUxq8v4beK8b9SvxsliJjHZFznjvkVLX7LQjBqw=="], + "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.107", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.107", "mime": "^4.1.0", "undici": "^8.7.0" }, "peerDependencies": { "effect": "^4.0.0-beta.107", "ioredis": ">=5.7.0 <6.0.0" } }, "sha512-k+6YNbV4Ck0L6YXtlgkvEnuP5tlxWD8EeWOrpn46PDqbGEwt4ONpRltTwm3tn2cyBXD0i+2P11cUH/6sdFagTA=="], - "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.101", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.0" }, "peerDependencies": { "effect": "^4.0.0-beta.101" } }, "sha512-g4L7XiyJSNJLJVhlslyg2zBCQsoKQf1y1gd+Yfd+3wD9ymC+m7ymbd/5FGqnT1aXV6E2AwRr4D/R1eyRUikvWQ=="], + "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.107", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.0" }, "peerDependencies": { "effect": "^4.0.0-beta.107" } }, "sha512-y6BqcRi86BfTJv+tvDrob4ozYVHxxlHYcn/zIQqZjXI9CvKnkgD6ng+38G1o45c4f2ucU+6HRI9POCmFdMoVGA=="], - "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.101", "", { "peerDependencies": { "effect": "^4.0.0-beta.101" } }, "sha512-s6AC7LXCEjCN+nKegKFY4MOi6bmT1+SLR9YHEYwhY3P5qyQQB4R5yYLgt+3J4EPp5fa3t4FIDdPEUwz9LdKm6g=="], + "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.107", "", { "peerDependencies": { "effect": "^4.0.0-beta.107" } }, "sha512-BuSSCUoXz6JSR30wT4Y0ukmJKvIFhm/gROwEeA0nLO5QYf33CdTunwX+q35+/MNOOLT8jL3xaDsz5R5aAF1vYQ=="], "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], @@ -3871,7 +3873,7 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "effect": ["effect@4.0.0-beta.101", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "multipasta": "^0.2.8", "toml": "^4.1.2", "uuid": "^14.0.1", "yaml": "^2.9.0" } }, "sha512-HjowumlIo+orthn4jMlEJPuzIYPBV+uq/XiciHWhiedLsXQpWHdNJHO5d59BVDP5s1LPuvERcktwFqRXnJqnhA=="], + "effect": ["effect@4.0.0-beta.107", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "uuid": "^14.0.1" } }, "sha512-OoBAv8eF+yanc+C6xhgEUnWeXUSHA6ynnscYqpkAY9GSnzZWystsIjBowVqCkLpHGlnRtdIqYT3wHwpOY6JDnQ=="], "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], @@ -4073,8 +4075,6 @@ "find-babel-config": ["find-babel-config@2.1.2", "", { "dependencies": { "json5": "^2.2.3" } }, "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg=="], - "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], "finity": ["finity@0.5.4", "", {}, "sha512-3l+5/1tuw616Lgb0QBimxfdd2TqaDGpfCBpfX6EqtFmqUV3FtQnVEX4Aa62DagYEqnsTIjZcTfbq9msDbXYgyA=="], @@ -4325,7 +4325,7 @@ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - "ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="], + "ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], @@ -4833,8 +4833,6 @@ "muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="], - "multipasta": ["multipasta@0.2.8", "", {}, "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q=="], - "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], "mysql2": ["mysql2@3.14.4", "", { "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.0", "long": "^5.2.1", "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" } }, "sha512-Cs/jx3WZPNrYHVz+Iunp9ziahaG5uFMvD2R8Zlmc194AqXNxt9HBNu7ZsPYrUtmJsF0egETCWIdMIYAwOGjL1w=="], @@ -5641,8 +5639,6 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - "toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="], - "toolbeam-docs-theme": ["toolbeam-docs-theme@0.4.8", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-b+5ynEFp4Woe5a22hzNQm42lD23t13ZMihVxHbzjA50zdcM9aOSJTIjdJ0PDSd4/50HbBXcpHiQsz6rM4N88ww=="], "topojson-client": ["topojson-client@3.1.0", "", { "dependencies": { "commander": "2" }, "bin": { "topo2geo": "bin/topo2geo", "topomerge": "bin/topomerge", "topoquantize": "bin/topoquantize" } }, "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw=="], @@ -6247,6 +6243,8 @@ "@dot/log/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "@effect/platform-node-shared/ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="], + "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], "@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -6301,10 +6299,6 @@ "@modelcontextprotocol/sdk/jose": ["jose@6.2.8", "", {}, "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ=="], - "@npmcli/config/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], - - "@npmcli/git/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], - "@npmcli/query/postcss-selector-parser": ["postcss-selector-parser@7.1.5", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw=="], "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.13", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.1.1", "@octokit/types": "^17.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-v2269YxL9Yf+x3d+gRI63FP0vFQEiWgLyBzxe/Y+0yFDg2B/Tzf5dhh9VNfccVAQnfcfwQWyk/y6Bn7rUXXs7A=="], diff --git a/package.json b/package.json index 7a20291b08..417c669ad1 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,10 @@ "packages/slack" ], "catalog": { - "@effect/opentelemetry": "4.0.0-beta.101", - "@effect/platform-node": "4.0.0-beta.101", - "@effect/sql-sqlite-bun": "4.0.0-beta.101", + "@effect/opentelemetry": "4.0.0-beta.107", + "@effect/platform-node": "4.0.0-beta.107", + "@effect/platform-node-shared": "4.0.0-beta.107", + "@effect/sql-sqlite-bun": "4.0.0-beta.107", "@npmcli/arborist": "9.4.0", "@types/bun": "1.3.13", "@types/cross-spawn": "6.0.6", @@ -70,7 +71,7 @@ "dompurify": "3.3.1", "drizzle-kit": "1.0.0-rc.2", "drizzle-orm": "1.0.0-rc.2", - "effect": "4.0.0-beta.101", + "effect": "4.0.0-beta.107", "ai": "6.0.168", "cross-spawn": "7.0.6", "hono": "4.10.7", @@ -154,6 +155,7 @@ "@opentui/core": "catalog:", "@opentui/keymap": "catalog:", "@opentui/solid": "catalog:", + "@effect/platform-node-shared": "catalog:", "@types/bun": "catalog:", "@types/node": "catalog:", "effect": "catalog:" @@ -164,6 +166,7 @@ "@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch", "@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", + "drizzle-orm@1.0.0-rc.2": "patches/drizzle-orm@1.0.0-rc.2.patch", "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", "@ai-sdk/mistral@3.0.51": "patches/@ai-sdk%2Fmistral@3.0.51.patch", "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", @@ -171,7 +174,6 @@ "@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch", "@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch", "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", - "effect@4.0.0-beta.101": "patches/effect@4.0.0-beta.101.patch", "@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch", "@ff-labs/fff-bun@0.10.1": "patches/@ff-labs%2Ffff-bun@0.10.1.patch" } diff --git a/packages/ai/src/protocols/shared.ts b/packages/ai/src/protocols/shared.ts index 95348bae4e..44442def68 100644 --- a/packages/ai/src/protocols/shared.ts +++ b/packages/ai/src/protocols/shared.ts @@ -202,14 +202,15 @@ export const errorText = (error: unknown) => { * decoder, and drops empty / `[DONE]` keep-alive events so the downstream * `decodeChunk` sees one JSON string per element. The SSE channel emits a * `Retry` control event on its error channel; we drop it here (we don't - * implement client-driven retries) so the public error channel stays - * `AIError`. + * implement client-driven retries). Decoder failures become provider output + * errors so the public error channel stays `AIError`. */ export const sseFraming = (bytes: Stream.Stream): Stream.Stream => bytes.pipe( Stream.decodeText(), Stream.pipeThroughChannel(Sse.decode()), Stream.catchTag("Retry", () => Stream.empty), + Stream.catchTag("SseError", (error) => Stream.fail(eventError("sse", error.message))), Stream.filter((event) => event.data.length > 0 && event.data !== "[DONE]"), Stream.map((event) => event.data), ) diff --git a/packages/ai/src/provider-error.ts b/packages/ai/src/provider-error.ts index 71cadab041..e81f1d7d03 100644 --- a/packages/ai/src/provider-error.ts +++ b/packages/ai/src/provider-error.ts @@ -57,7 +57,7 @@ export const isContextOverflowFailure = (failure: unknown) => ? failure.reason._tag === "InvalidRequest" && failure.reason.classification === "context-overflow" : Schema.is(ProviderErrorEvent)(failure) && failure.classification === "context-overflow" -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const QUOTA_CODES = new Set(["insufficient_quota", "usage_not_included", "billing_error"]) const SERVER_CODES = new Set([ "api_error", diff --git a/packages/ai/src/schema/errors.ts b/packages/ai/src/schema/errors.ts index aeeabb4b98..08ea268cea 100644 --- a/packages/ai/src/schema/errors.ts +++ b/packages/ai/src/schema/errors.ts @@ -148,7 +148,7 @@ export const AIErrorReason = Schema.Union([ ]).pipe(Schema.toTaggedUnion("_tag")) export type AIErrorReason = Schema.Schema.Type -export class AIError extends Schema.TaggedErrorClass()("AI.Error", { +export class AIError extends Schema.TaggedError()("AI.Error", { module: Schema.String, method: Schema.String, reason: AIErrorReason, diff --git a/packages/ai/test/provider/bedrock-mantle.test.ts b/packages/ai/test/provider/bedrock-mantle.test.ts index 6eb7ffa9e2..f39f0567f9 100644 --- a/packages/ai/test/provider/bedrock-mantle.test.ts +++ b/packages/ai/test/provider/bedrock-mantle.test.ts @@ -75,7 +75,6 @@ describe("Amazon Bedrock Mantle provider", () => { }), ), ), - Effect.flip, ) expect(seen).toEqual([{ url: "https://mantle.test/v1/chat/completions", authorization: "Bearer test-key" }]) diff --git a/packages/ai/test/schema.test.ts b/packages/ai/test/schema.test.ts index e0833c2ed8..692585ef69 100644 --- a/packages/ai/test/schema.test.ts +++ b/packages/ai/test/schema.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test" -import { Effect, Schema } from "effect" +import { Effect, Schema, Stream } from "effect" import * as OpenAIChat from "../src/protocols/openai-chat.js" import * as OpenAIResponses from "../src/protocols/openai-responses.js" import { @@ -90,6 +90,17 @@ describe("AI.Usage", () => { expect(ProviderShared.sumTokens()).toBeUndefined() }) + test("sseFraming maps decoder failures to AI errors", async () => { + const error = await Effect.runPromise( + ProviderShared.sseFraming( + Stream.make(new TextEncoder().encode(`data: ${"x".repeat(10 * 1024 * 1024)}`)), + ).pipe(Stream.runCollect, Effect.flip), + ) + + expect(error).toBeInstanceOf(AIError) + expect(error.reason._tag).toBe("InvalidProviderOutput") + }) + test("visibleOutputTokens clamps reasoning > output to zero", () => { expect(new Usage({ outputTokens: 10, reasoningTokens: 4 }).visibleOutputTokens).toBe(6) expect(new Usage({ outputTokens: 10 }).visibleOutputTokens).toBe(10) diff --git a/packages/app/src/utils/session-message.ts b/packages/app/src/utils/session-message.ts index 8b24a7ba60..36ce74c741 100644 --- a/packages/app/src/utils/session-message.ts +++ b/packages/app/src/utils/session-message.ts @@ -10,7 +10,7 @@ import { Option, Schema } from "effect" const emptyTokens = { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } } const emptyModel: { id: string; providerID: string; variant?: string } = { id: "", providerID: "" } -const decodeToolInput = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeToolInput = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) export function compareMessages(a: Pick, b: Pick) { const left = messageKey(a) diff --git a/packages/cli/src/acp/error.ts b/packages/cli/src/acp/error.ts index 50dec3f4f6..004c9b1467 100644 --- a/packages/cli/src/acp/error.ts +++ b/packages/cli/src/acp/error.ts @@ -1,36 +1,36 @@ import { RequestError } from "@agentclientprotocol/sdk" import { Schema } from "effect" -export class SessionNotFoundError extends Schema.TaggedErrorClass()("ACPSessionNotFoundError", { +export class SessionNotFoundError extends Schema.TaggedError()("ACPSessionNotFoundError", { sessionId: Schema.String, }) {} -export class InvalidConfigOptionError extends Schema.TaggedErrorClass()( +export class InvalidConfigOptionError extends Schema.TaggedError()( "ACPInvalidConfigOptionError", { configId: Schema.String }, ) {} -export class InvalidModelError extends Schema.TaggedErrorClass()("ACPInvalidModelError", { +export class InvalidModelError extends Schema.TaggedError()("ACPInvalidModelError", { modelId: Schema.String, providerId: Schema.optional(Schema.String), }) {} -export class InvalidEffortError extends Schema.TaggedErrorClass()("ACPInvalidEffortError", { +export class InvalidEffortError extends Schema.TaggedError()("ACPInvalidEffortError", { effort: Schema.String, }) {} -export class InvalidModeError extends Schema.TaggedErrorClass()("ACPInvalidModeError", { +export class InvalidModeError extends Schema.TaggedError()("ACPInvalidModeError", { mode: Schema.String, }) {} -export class AuthRequiredError extends Schema.TaggedErrorClass()("ACPAuthRequiredError", {}) {} +export class AuthRequiredError extends Schema.TaggedError()("ACPAuthRequiredError", {}) {} -export class UnknownAuthMethodError extends Schema.TaggedErrorClass()( +export class UnknownAuthMethodError extends Schema.TaggedError()( "ACPUnknownAuthMethodError", { methodId: Schema.String }, ) {} -export class ServiceFailureError extends Schema.TaggedErrorClass()("ACPServiceFailureError", { +export class ServiceFailureError extends Schema.TaggedError()("ACPServiceFailureError", { safeMessage: Schema.String, service: Schema.optional(Schema.String), errorName: Schema.optional(Schema.String), diff --git a/packages/client/package.json b/packages/client/package.json index 8cbc7ae00c..de12a61080 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -37,7 +37,7 @@ "@opencode-ai/protocol": "workspace:*" }, "peerDependencies": { - "effect": "4.0.0-beta.101", + "effect": "4.0.0-beta.107", "solid-js": ">=1.9.0" }, "peerDependenciesMeta": { diff --git a/packages/client/src/effect/generated/client-error.ts b/packages/client/src/effect/generated/client-error.ts index bcc65d9bdd..858cb704f5 100644 --- a/packages/client/src/effect/generated/client-error.ts +++ b/packages/client/src/effect/generated/client-error.ts @@ -1,5 +1,5 @@ import { Schema } from "effect" -export class ClientError extends Schema.TaggedErrorClass()("ClientError", { +export class ClientError extends Schema.TaggedError()("ClientError", { cause: Schema.Defect(), }) {} diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index 3253229787..aea5ccc624 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -18,13 +18,6 @@ export type SessionForkBoundary = { type: "before"; messageID: string } | { type export type MoneyUSD = number -export type TokenUsageInfo = { - input: number - output: number - reasoning: number - cache: { read: number; write: number } -} - export type LocationRef = { directory: string; workspaceID?: string } export type FileDiffInfo = { @@ -35,105 +28,22 @@ export type FileDiffInfo = { status: "added" | "deleted" | "modified" } -export type SessionMessageAgentSelected = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - type: "agent-switched" - agent: string - previous?: string -} - export type PromptBase64 = string export type PromptFileSource = { type: "inline" } | { type: "uri"; uri: string } export type PromptMention = { start: number; end: number; text: string } -export type SessionMessageSynthetic = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - text: string - description?: string - type: "synthetic" -} - -export type SessionMessageSystem = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - type: "system" - text: string - description?: string -} - -export type SessionMessageSkill = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - type: "skill" - skill: string - name: string - text: string -} - -export type SessionMessageShell = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number; completed?: number } - type: "shell" - shellID: string - command: string - status: "running" | "exited" | "timeout" | "killed" - exit?: number | "Infinity" | "-Infinity" | "NaN" - output?: { output: string; cursor: number; size: number; truncated: boolean } -} - -export type SessionMessageProviderState = { [x: string]: JsonValue } - export type SessionMessageToolStateStreaming = { status: "streaming"; input: string } -export type SessionMessageToolStateRunning = { - status: "running" - input: { [x: string]: JsonValue } - metadata: { [x: string]: JsonValue } -} - export type ToolTextContent = { type: "text"; text: string } -export type ToolFileContent = { type: "file"; uri: string; mime: string; name?: string | null } - export type SessionStructuredError = { type: string; message: string; status?: number } -export type SessionMessageCompactionRunning = { - type: "compaction" - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - status: "running" - reason: "auto" | "manual" - summary: string - recent: string -} - -export type SessionMessageCompactionCompleted = { - type: "compaction" - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - status: "completed" - reason: "auto" | "manual" - summary: string - recent: string -} - export type SessionActive = { type: "running" } export type SessionInboxDelivery = "steer" | "queue" -export type SessionInboxSyntheticPayload = { text: string; description?: string; metadata?: { [x: string]: JsonValue } } - export type SessionInboxCompactionPayload = {} export type InstructionEntryKey = string @@ -142,69 +52,20 @@ export type SessionGenerateResponse = { data: { text: string } } export type SessionInboxSyntheticPayload1 = { text: string; description?: string; metadata?: { [x: string]: any } } -export type ShellInfo = { - id: string - status: "running" | "exited" | "timeout" | "killed" - command: string - cwd: string - shell: string - file: string - pid?: number - exit?: number - metadata: { [x: string]: any } - time: { started: number; completed?: number } -} - -export type SessionMessageProviderState4 = { [x: string]: any } - -export type SessionMessageProviderState5 = { [x: string]: any } - -export type SessionMessageProviderState6 = { [x: string]: any } - -export type SessionMessageProviderState7 = { [x: string]: any } +export type SessionMessageProviderState1 = { [x: string]: any } export type ToolFileContent1 = { type: "file"; uri: string; mime: string; name?: string | undefined } -export type SessionMessageProviderState8 = { [x: string]: any } - -export type SessionMessageProviderState9 = { [x: string]: any } - export type EventLogSynced = { type: "log.synced"; aggregateID: string; seq?: number } export type ModelReasoningField = "reasoning" | "reasoning_content" | "reasoning_text" | (string & {}) export type ModelMaxTokensField = "max_completion_tokens" | "max_tokens" -export type ModelCapabilities = { tools: boolean; input: Array; output: Array } - -export type ModelVariant = { - id: string - settings?: { [x: string]: any } - headers?: { [x: string]: string } - body?: { [x: string]: any } -} - export type MoneyUSDPerMillionTokens = number export type GenerateTextResponse = { data: { text: string } } -export type ProviderInfo = { - id: string - integrationID?: string - name: string - activation: "auto" | "enabled" | "disabled" - package: string - settings?: { [x: string]: any } - headers?: { [x: string]: string } - body?: { [x: string]: any } -} - -export type FormWhen = { - key: string - op: "eq" | "neq" - value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean -} - export type FormOption = { value: string; label: string; description?: string } export type FormExternalField = { key: string; type: "external"; url: string; title?: string; description?: string } @@ -217,50 +78,6 @@ export type ConnectionCredentialInfo = { type: "credential"; id: string; label: export type ConnectionEnvInfo = { type: "env"; name: string } -export type IntegrationAttemptStatus = - | { - status: "pending" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "complete" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "failed" - message: string - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "expired" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - -export type IntegrationCommandAttempt = { - attemptID: string - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } -} - -export type IntegrationCommandAttemptStatus = - | { - status: "pending" - message?: string - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "complete" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "failed" - message: string - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - | { - status: "expired" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } - } - export type McpStatusConnected = { status: "connected" } export type McpStatusPending = { status: "pending" } @@ -291,8 +108,6 @@ export type ProjectTime = { created: number; updated: number; initialized?: numb export type ProjectCurrent = { id: string; directory: string; canonical: string } -export type FormMetadata = { [x: string]: JsonValue } - export type FormValue = string | number | boolean | Array export type PermissionSource = { type: "tool"; messageID: string; id: string } @@ -339,19 +154,6 @@ export type SessionStatus = } | { type: "busy" } -export type ShellInfo1 = { - id: string - status: "running" | "exited" | "timeout" | "killed" - command: string - cwd: string - shell: string - file: string - pid?: number - exit?: number - metadata: { [x: string]: JsonValue } - time: { started: number; completed?: number } -} - export type ReferenceLocalSource = { type: "local"; path: string; description?: string; hidden?: boolean } export type ReferenceGitSource = { @@ -379,15 +181,6 @@ export type WebSearchProvider = { id: string; name: string } export type WebSearchResult = { url: string; title?: string; content?: string; time: { published?: number } } -export type SessionMessageModelSelected = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - type: "model-switched" - model: ModelRef - previous?: ModelRef -} - export type CommandInfo = { name: string template: string @@ -405,19 +198,63 @@ export type ProviderRequest = { export type PermissionRule = { action: string; resource: string; effect: PermissionEffect } -export type SessionMessageLocationSwitched = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - type: "location-switched" - location: LocationRef - projectID?: string - subpath?: string - previous?: { location: LocationRef; projectID?: string; subpath?: string } +export type TokenUsageInfo = { + input: number + output: number + reasoning: number + cache: { read: number; write: number } } export type SessionInboxMovePayload = { location: LocationRef; projectID: string; subpath?: string } +export type V2EventServerConnected = { + id: string + metadata?: { [x: string]: any } | undefined + location?: LocationRef | undefined + type: "server.connected" + data: {} +} + +export type SessionMessageProviderState = { [x: string]: JsonValue } + +export type SessionMessageToolStateRunning = { + status: "running" + input: { [x: string]: JsonValue } + metadata: { [x: string]: JsonValue } +} + +export type SessionInboxSyntheticPayload = { text: string; description?: string; metadata?: { [x: string]: JsonValue } } + +export type FormMetadata = { [x: string]: JsonValue } + +export type PromptFileAttachment = { + data: PromptBase64 + mime: string + source: PromptFileSource + name?: string + description?: string + mention?: PromptMention +} + +export type PromptAgentAttachment = { name: string; mention?: PromptMention } + +export type PromptSkillAttachment = { id: string; name: string; text: string; mention?: PromptMention } + +export type ToolFileContent = { type: "file"; uri: string; mime: string; name?: string | null } + +export type SessionMessageAssistantRetry = { attempt: number; at: number; error: SessionStructuredError } + +export type SessionInboxCompaction = { + id: string + sessionID: string + timeCreated: number + type: "compaction" + payload: SessionInboxCompactionPayload + delivery: SessionInboxDelivery +} + +export type InstructionEntryInfo = { key: InstructionEntryKey; value: JsonValue } + export type SessionCreated = { id: string created: number @@ -519,6 +356,16 @@ export type SessionInboxCancelled = { data: { sessionID: string; inboxID: string } } +export type SessionInboxDeliveryChanged = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.inbox.delivery.changed" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; inboxID: string; delivery: SessionInboxDelivery } +} + export type SessionExecutionStarted = { id: string created: number @@ -539,6 +386,16 @@ export type SessionExecutionSucceeded = { data: { sessionID: string } } +export type SessionExecutionFailed = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.execution.failed" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; error: SessionStructuredError } +} + export type SessionExecutionInterrupted = { id: string created: number @@ -589,24 +446,6 @@ export type SessionStepStarted = { data: { sessionID: string; assistantMessageID: string; agent: string; model: ModelRef; snapshot?: string } } -export type SessionStepEnded = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.step.ended" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { - sessionID: string - assistantMessageID: string - finish: "stop" | "length" | "tool-calls" | "content-filter" | "error" | "unknown" - cost: MoneyUSD - tokens: TokenUsageInfo - snapshot?: string - files?: Array - } -} - export type SessionTextStarted = { id: string created: number @@ -637,24 +476,14 @@ export type SessionToolInputEnded = { data: { sessionID: string; assistantMessageID: string; id: string; text: string } } -export type SessionCompactionStarted = { +export type SessionRetryScheduled = { id: string created: number metadata?: { [x: string]: any } - type: "session.compaction.started" + type: "session.retry.scheduled" durable: { aggregateID: string; seq: number; version: 1 } location?: LocationRef - data: { sessionID: string; reason: "auto" | "manual"; recent: string; inputID?: string } -} - -export type SessionCompactionEnded = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.compaction.ended" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; reason: "auto" | "manual"; text: string; recent: string } + data: { sessionID: string; assistantMessageID: string; attempt: number; at: number; error: SessionStructuredError } } export type SessionRevertCleared = { @@ -677,16 +506,6 @@ export type SessionRevertCommitted = { data: { sessionID: string; to: string } } -export type SessionUsageRecorded = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.usage.recorded" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; source: "title" | "compaction"; cost: MoneyUSD; tokens: TokenUsageInfo } -} - export type ModelsDevRefreshed = { id: string created: number @@ -732,15 +551,6 @@ export type AgentUpdated = { data: {} } -export type SessionUsageUpdated = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.usage.updated" - location?: LocationRef - data: { sessionID: string; cost: MoneyUSD; tokens: TokenUsageInfo } -} - export type SessionTextDelta = { id: string created: number @@ -1037,161 +847,30 @@ export type McpResourcesChanged = { data: { server: string } } -export type V2EventServerConnected = { +export type ShellInfo = { id: string - metadata?: { [x: string]: any } | undefined - location?: LocationRef | undefined - type: "server.connected" - data: {} + status: "running" | "exited" | "timeout" | "killed" + command: string + cwd: string + shell: string + file: string + pid?: number + exit?: number + metadata: { [x: string]: any } + time: { started: number; completed?: number } } -export type SessionRevert = { messageID: string; partID?: string; snapshot?: string; files?: Array } - -export type PromptFileAttachment = { - data: PromptBase64 - mime: string - source: PromptFileSource - name?: string - description?: string - mention?: PromptMention -} - -export type PromptAgentAttachment = { name: string; mention?: PromptMention } - -export type PromptSkillAttachment = { id: string; name: string; text: string; mention?: PromptMention } - -export type SessionMessageAssistantText = { type: "text"; text: string; state?: SessionMessageProviderState } - -export type SessionMessageAssistantReasoning = { - type: "reasoning" - text: string - state?: SessionMessageProviderState - time?: { created: number; completed?: number } -} - -export type ToolContent = ToolTextContent | ToolFileContent - -export type SessionMessageAssistantRetry = { attempt: number; at: number; error: SessionStructuredError } - -export type SessionMessageCompactionFailed = { - type: "compaction" +export type ShellInfo1 = { id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - status: "failed" - reason: "auto" | "manual" - error: SessionStructuredError -} - -export type SessionExecutionFailed = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.execution.failed" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; error: SessionStructuredError } -} - -export type SessionStepFailed = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.step.failed" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { - sessionID: string - assistantMessageID: string - error: SessionStructuredError - cost?: MoneyUSD - tokens?: TokenUsageInfo - snapshot?: string - files?: Array - } -} - -export type SessionRetryScheduled = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.retry.scheduled" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; assistantMessageID: string; attempt: number; at: number; error: SessionStructuredError } -} - -export type SessionCompactionFailed = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.compaction.failed" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; reason: "auto" | "manual"; error: SessionStructuredError; inputID?: string } -} - -export type SessionInboxDeliveryChanged = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.inbox.delivery.changed" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; inboxID: string; delivery: SessionInboxDelivery } -} - -export type SessionInboxSynthetic = { - id: string - sessionID: string - timeCreated: number - type: "synthetic" - payload: SessionInboxSyntheticPayload - delivery: SessionInboxDelivery -} - -export type SessionInboxCompaction = { - id: string - sessionID: string - timeCreated: number - type: "compaction" - payload: SessionInboxCompactionPayload - delivery: SessionInboxDelivery -} - -export type InstructionEntryInfo = { key: InstructionEntryKey; value: JsonValue } - -export type SessionShellStarted = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.shell.started" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; shell: ShellInfo } -} - -export type SessionShellEnded = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.shell.ended" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { - sessionID: string - shell: ShellInfo - output: { output: string; cursor: number; size: number; truncated: boolean } - } -} - -export type ShellCreated = { - id: string - created: number - metadata?: { [x: string]: any } - type: "shell.created" - location?: LocationRef - data: { info: ShellInfo } + status: "running" | "exited" | "timeout" | "killed" + command: string + cwd: string + shell: string + file: string + pid?: number + exit?: number + metadata: { [x: string]: JsonValue } + time: { started: number; completed?: number } } export type SessionTextEnded = { @@ -1206,7 +885,7 @@ export type SessionTextEnded = { assistantMessageID: string ordinal: number text: string - state?: SessionMessageProviderState4 + state?: SessionMessageProviderState1 } } @@ -1217,7 +896,7 @@ export type SessionReasoningStarted = { type: "session.reasoning.started" durable: { aggregateID: string; seq: number; version: 1 } location?: LocationRef - data: { sessionID: string; assistantMessageID: string; ordinal: number; state?: SessionMessageProviderState5 } + data: { sessionID: string; assistantMessageID: string; ordinal: number; state?: SessionMessageProviderState1 } } export type SessionReasoningEnded = { @@ -1232,7 +911,7 @@ export type SessionReasoningEnded = { assistantMessageID: string ordinal: number text: string - state?: SessionMessageProviderState6 + state?: SessionMessageProviderState1 } } @@ -1249,18 +928,68 @@ export type SessionToolCalled = { id: string input: { [x: string]: any } executed: boolean - state?: SessionMessageProviderState7 + state?: SessionMessageProviderState1 } } export type ToolContent1 = ToolTextContent | ToolFileContent1 +export type SessionCompactionStarted = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.compaction.started" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; reason: "auto" | "manual"; recent: string; inputID?: string } +} + +export type SessionCompactionEnded = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.compaction.ended" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; reason: "auto" | "manual"; text: string; recent: string } +} + +export type SessionCompactionFailed = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.compaction.failed" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; reason: "auto" | "manual"; error: SessionStructuredError; inputID?: string } +} + export type ModelCompatibility = { reasoningField?: ModelReasoningField maxTokensField?: ModelMaxTokensField requireFinishReason?: boolean } +export type ModelVariant = { + id: string + settings?: { [x: string]: any } + headers?: { [x: string]: string } + body?: { [x: string]: any } +} + +export type ProviderInfo = { + id: string + integrationID?: string + name: string + activation: "auto" | "enabled" | "disabled" + package: string + settings?: { [x: string]: any } + headers?: { [x: string]: string } + body?: { [x: string]: any } +} + +export type ModelCapabilities = { tools: boolean; input: Array; output: Array } + export type ModelCost = { tier?: { type: "context"; size: number } input: MoneyUSDPerMillionTokens @@ -1268,71 +997,6 @@ export type ModelCost = { cache: { read: MoneyUSDPerMillionTokens; write: MoneyUSDPerMillionTokens } } -export type FormNumberField = { - key: string - title?: string - description?: string - required?: boolean - when?: Array - type: "number" - minimum?: number | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "Infinity" | "-Infinity" | "NaN" - default?: number | "Infinity" | "-Infinity" | "NaN" -} - -export type FormIntegerField = { - key: string - title?: string - description?: string - required?: boolean - when?: Array - type: "integer" - minimum?: number | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "Infinity" | "-Infinity" | "NaN" - default?: number | "Infinity" | "-Infinity" | "NaN" -} - -export type FormBooleanField = { - key: string - title?: string - description?: string - required?: boolean - when?: Array - type: "boolean" - default?: boolean -} - -export type FormStringField = { - key: string - title?: string - description?: string - required?: boolean - when?: Array - type: "string" - format?: "email" | "uri" | "date" | "date-time" - minLength?: number - maxLength?: number - pattern?: string - placeholder?: string - default?: string - options?: Array - custom?: boolean -} - -export type FormMultiselectField = { - key: string - title?: string - description?: string - required?: boolean - when?: Array - type: "multiselect" - options: Array - minItems?: number - maxItems?: number - custom?: boolean - default?: Array -} - export type ConnectionInfo = ConnectionCredentialInfo | ConnectionEnvInfo export type McpServer = { @@ -1410,6 +1074,317 @@ export type PtyUpdated = { data: { info: Pty } } +export type SessionStatus2 = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.status" + location?: LocationRef + data: { sessionID: string; status: SessionStatus } +} + +export type ReferenceSource = ReferenceLocalSource | ReferenceGitSource + +export type WorktreeList = Array + +export type VcsInfo = { branch: VcsBranch } + +export type PermissionRuleset = Array + +export type SessionStepEnded = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.step.ended" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { + sessionID: string + assistantMessageID: string + finish: "stop" | "length" | "tool-calls" | "content-filter" | "error" | "unknown" + cost: MoneyUSD + tokens: TokenUsageInfo + snapshot?: string + files?: Array + } +} + +export type SessionUsageRecorded = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.usage.recorded" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; source: "title" | "compaction"; cost: MoneyUSD; tokens: TokenUsageInfo } +} + +export type SessionUsageUpdated = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.usage.updated" + location?: LocationRef + data: { sessionID: string; cost: MoneyUSD; tokens: TokenUsageInfo } +} + +export type SessionStepFailed = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.step.failed" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { + sessionID: string + assistantMessageID: string + error: SessionStructuredError + cost?: MoneyUSD + tokens?: TokenUsageInfo + snapshot?: string + files?: Array + } +} + +export type SessionInboxMove = { + id: string + sessionID: string + timeCreated: number + type: "move" + payload: SessionInboxMovePayload + delivery: SessionInboxDelivery +} + +export type SessionRevert = { messageID: string; partID?: string; snapshot?: string; files?: Array } + +export type SessionMessageAgentSelected = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + type: "agent-switched" + agent: string + previous?: string +} + +export type SessionMessageModelSelected = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + type: "model-switched" + model: ModelRef + previous?: ModelRef +} + +export type SessionMessageLocationSwitched = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + type: "location-switched" + location: LocationRef + projectID?: string + subpath?: string + previous?: { location: LocationRef; projectID?: string; subpath?: string } +} + +export type SessionMessageSynthetic = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + text: string + description?: string + type: "synthetic" +} + +export type SessionMessageSystem = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + type: "system" + text: string + description?: string +} + +export type SessionMessageSkill = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + type: "skill" + skill: string + name: string + text: string +} + +export type SessionMessageShell = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number; completed?: number } + type: "shell" + shellID: string + command: string + status: "running" | "exited" | "timeout" | "killed" + exit?: number | ("Infinity" | "-Infinity" | "NaN") + output?: { output: string; cursor: number; size: number; truncated: boolean } +} + +export type SessionMessageCompactionRunning = { + type: "compaction" + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + status: "running" + reason: "auto" | "manual" + summary: string + recent: string +} + +export type SessionMessageCompactionCompleted = { + type: "compaction" + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + status: "completed" + reason: "auto" | "manual" + summary: string + recent: string +} + +export type SessionMessageCompactionFailed = { + type: "compaction" + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + status: "failed" + reason: "auto" | "manual" + error: SessionStructuredError +} + +export type SessionMessageAssistantText = { type: "text"; text: string; state?: SessionMessageProviderState } + +export type SessionMessageAssistantReasoning = { + type: "reasoning" + text: string + state?: SessionMessageProviderState + time?: { created: number; completed?: number } +} + +export type SessionInboxSynthetic = { + id: string + sessionID: string + timeCreated: number + type: "synthetic" + payload: SessionInboxSyntheticPayload + delivery: SessionInboxDelivery +} + +export type FormWhen = { + key: string + op: "eq" | "neq" + value: string | (number | ("Infinity" | "-Infinity" | "NaN")) | boolean +} + +export type ToolContent = ToolTextContent | ToolFileContent + +export type SessionShellStarted = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.shell.started" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; shell: ShellInfo } +} + +export type SessionShellEnded = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.shell.ended" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { + sessionID: string + shell: ShellInfo + output: { output: string; cursor: number; size: number; truncated: boolean } + } +} + +export type ShellCreated = { + id: string + created: number + metadata?: { [x: string]: any } + type: "shell.created" + location?: LocationRef + data: { info: ShellInfo } +} + +export type SessionToolSuccess = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.tool.success" + durable: { aggregateID: string; seq: number; version: 2 } + location?: LocationRef + data: { + sessionID: string + assistantMessageID: string + id: string + content: [ToolContent1, ...Array] + metadata?: { [x: string]: JsonValue } + executed: boolean + resultState?: SessionMessageProviderState1 + } +} + +export type SessionToolFailed = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.tool.failed" + durable: { aggregateID: string; seq: number; version: 2 } + location?: LocationRef + data: { + sessionID: string + assistantMessageID: string + id: string + error: SessionStructuredError + content?: [ToolContent1, ...Array] + metadata?: { [x: string]: JsonValue } + executed: boolean + resultState?: SessionMessageProviderState1 + } +} + +export type ModelInfo = { + id: string + modelID: string + providerID: string + family?: string + name: string + compatibility?: ModelCompatibility + package?: string + settings?: { [x: string]: any } + headers?: { [x: string]: string } + body?: { [x: string]: any } + capabilities: ModelCapabilities + variants: Array + time: { released: number } + cost: Array + status: "alpha" | "beta" | "deprecated" | "active" + enabled: boolean + limit: { context: number; input?: number; output: number } +} + +export type FormState = { status: "pending" } | { status: "answered"; answer: FormAnswer } | { status: "cancelled" } + +export type FormReplied = { + id: string + created: number + metadata?: { [x: string]: any } + type: "form.replied" + location?: LocationRef + data: { id: string; sessionID: string; answer: FormAnswer } +} + export type FormStringField1 = { key: string title?: string @@ -1475,189 +1450,6 @@ export type FormMultiselectField1 = { default?: Array } -export type SessionStatus2 = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.status" - location?: LocationRef - data: { sessionID: string; status: SessionStatus } -} - -export type ReferenceSource = ReferenceLocalSource | ReferenceGitSource - -export type WorktreeList = Array - -export type VcsInfo = { branch: VcsBranch } - -export type PermissionRuleset = Array - -export type SessionInboxMove = { - id: string - sessionID: string - timeCreated: number - type: "move" - payload: SessionInboxMovePayload - delivery: SessionInboxDelivery -} - -export type SessionInfo = { - id: string - parentID?: string - fork?: { sessionID: string; boundary: SessionForkBoundary } - projectID: string - agent?: string - model?: ModelRef - cost: MoneyUSD - tokens: TokenUsageInfo - time: { created: number; updated: number; archived?: number } - title?: string - location: LocationRef - subpath?: string - revert?: SessionRevert -} - -export type SessionRevertStaged = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.revert.staged" - durable: { aggregateID: string; seq: number; version: 1 } - location?: LocationRef - data: { sessionID: string; revert: SessionRevert } -} - -export type SessionMessageUser = { - id: string - metadata?: { [x: string]: JsonValue } - time: { created: number } - text: string - files?: Array - agents?: Array - skills?: Array - type: "user" -} - -export type SessionInboxUserPayload = { - text: string - files?: Array - agents?: Array - skills?: Array - metadata?: { [x: string]: JsonValue } -} - -export type SessionInboxUserPayload1 = { - text: string - files?: Array - agents?: Array - skills?: Array - metadata?: { [x: string]: any } -} - -export type SessionMessageToolStateCompleted = { - status: "completed" - input: { [x: string]: JsonValue } - content: [ToolContent, ...Array] - metadata?: { [x: string]: JsonValue } -} - -export type SessionMessageToolStateError = { - status: "error" - input: { [x: string]: JsonValue } - error: SessionStructuredError - content?: [ToolContent, ...Array] - metadata?: { [x: string]: JsonValue } -} - -export type SessionMessageCompaction = - | SessionMessageCompactionRunning - | SessionMessageCompactionCompleted - | SessionMessageCompactionFailed - -export type SessionToolSuccess = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.tool.success" - durable: { aggregateID: string; seq: number; version: 2 } - location?: LocationRef - data: { - sessionID: string - assistantMessageID: string - id: string - content: [ToolContent1, ...Array] - metadata?: { [x: string]: JsonValue } - executed: boolean - resultState?: SessionMessageProviderState8 - } -} - -export type SessionToolFailed = { - id: string - created: number - metadata?: { [x: string]: any } - type: "session.tool.failed" - durable: { aggregateID: string; seq: number; version: 2 } - location?: LocationRef - data: { - sessionID: string - assistantMessageID: string - id: string - error: SessionStructuredError - content?: [ToolContent1, ...Array] - metadata?: { [x: string]: JsonValue } - executed: boolean - resultState?: SessionMessageProviderState9 - } -} - -export type ModelInfo = { - id: string - modelID: string - providerID: string - family?: string - name: string - compatibility?: ModelCompatibility - package?: string - settings?: { [x: string]: any } - headers?: { [x: string]: string } - body?: { [x: string]: any } - capabilities: ModelCapabilities - variants: Array - time: { released: number } - cost: Array - status: "alpha" | "beta" | "deprecated" | "active" - enabled: boolean - limit: { context: number; input?: number; output: number } -} - -export type FormField = - | FormStringField - | FormNumberField - | FormIntegerField - | FormBooleanField - | FormMultiselectField - | FormExternalField - -export type FormState = { status: "pending" } | { status: "answered"; answer: FormAnswer } | { status: "cancelled" } - -export type FormReplied = { - id: string - created: number - metadata?: { [x: string]: any } - type: "form.replied" - location?: LocationRef - data: { id: string; sessionID: string; answer: FormAnswer } -} - -export type FormField1 = - | FormStringField1 - | FormNumberField1 - | FormIntegerField1 - | FormBooleanField1 - | FormMultiselectField1 - | FormExternalField - export type ReferenceInfo = { name: string path: string @@ -1845,6 +1637,155 @@ export type ConfigEntry = | { type: "agents"; path: string } | { type: "claude"; path: string } +export type SessionInfo = { + id: string + parentID?: string + fork?: { sessionID: string; boundary: SessionForkBoundary } + projectID: string + agent?: string + model?: ModelRef + cost: MoneyUSD + tokens: TokenUsageInfo + time: { created: number; updated: number; archived?: number } + title?: string + location: LocationRef + subpath?: string + revert?: SessionRevert +} + +export type SessionRevertStaged = { + id: string + created: number + metadata?: { [x: string]: any } + type: "session.revert.staged" + durable: { aggregateID: string; seq: number; version: 1 } + location?: LocationRef + data: { sessionID: string; revert: SessionRevert } +} + +export type SessionMessageCompaction = + | SessionMessageCompactionRunning + | SessionMessageCompactionCompleted + | SessionMessageCompactionFailed + +export type SessionMessageUser = { + id: string + metadata?: { [x: string]: JsonValue } + time: { created: number } + text: string + files?: Array + agents?: Array + skills?: Array + type: "user" +} + +export type SessionInboxUserPayload = { + text: string + files?: Array + agents?: Array + skills?: Array + metadata?: { [x: string]: JsonValue } +} + +export type SessionInboxUserPayload1 = { + text: string + files?: Array + agents?: Array + skills?: Array + metadata?: { [x: string]: any } +} + +export type IntegrationAttemptStatus = + | { + status: "pending" + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "complete" + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "failed" + message: string + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "expired" + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + +export type IntegrationCommandAttempt = { + attemptID: string + time: { created: number | ("Infinity" | "-Infinity" | "NaN"); expires: number | ("Infinity" | "-Infinity" | "NaN") } +} + +export type IntegrationCommandAttemptStatus = + | { + status: "pending" + message?: string + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "complete" + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "failed" + message: string + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + | { + status: "expired" + time: { + created: number | ("Infinity" | "-Infinity" | "NaN") + expires: number | ("Infinity" | "-Infinity" | "NaN") + } + } + +export type SessionMessageToolStateCompleted = { + status: "completed" + input: { [x: string]: JsonValue } + content: [ToolContent, ...Array] + metadata?: { [x: string]: JsonValue } +} + +export type SessionMessageToolStateError = { + status: "error" + input: { [x: string]: JsonValue } + error: SessionStructuredError + content?: [ToolContent, ...Array] + metadata?: { [x: string]: JsonValue } +} + +export type FormField1 = + | FormStringField1 + | FormNumberField1 + | FormIntegerField1 + | FormBooleanField1 + | FormMultiselectField1 + | FormExternalField + export type SessionsResponse = { data: Array; cursor: { previous?: string | null; next?: string | null } } export type SessionInboxUser = { @@ -1862,6 +1803,71 @@ export type SessionInboxItem = | { type: "compaction"; payload: SessionInboxCompactionPayload; delivery: SessionInboxDelivery } | { type: "move"; payload: SessionInboxMovePayload; delivery: SessionInboxDelivery } +export type FormStringField = { + key: string + title?: string + description?: string + required?: boolean + when?: Array + type: "string" + format?: "email" | "uri" | "date" | "date-time" + minLength?: number + maxLength?: number + pattern?: string + placeholder?: string + default?: string + options?: Array + custom?: boolean +} + +export type FormNumberField = { + key: string + title?: string + description?: string + required?: boolean + when?: Array + type: "number" + minimum?: number | ("Infinity" | "-Infinity" | "NaN") + maximum?: number | ("Infinity" | "-Infinity" | "NaN") + default?: number | ("Infinity" | "-Infinity" | "NaN") +} + +export type FormIntegerField = { + key: string + title?: string + description?: string + required?: boolean + when?: Array + type: "integer" + minimum?: number | ("Infinity" | "-Infinity" | "NaN") + maximum?: number | ("Infinity" | "-Infinity" | "NaN") + default?: number | ("Infinity" | "-Infinity" | "NaN") +} + +export type FormBooleanField = { + key: string + title?: string + description?: string + required?: boolean + when?: Array + type: "boolean" + default?: boolean +} + +export type FormMultiselectField = { + key: string + title?: string + description?: string + required?: boolean + when?: Array + type: "multiselect" + options: Array + minItems?: number + maxItems?: number + custom?: boolean + default?: Array +} + export type SessionMessageAssistantTool = { type: "tool" id: string @@ -1877,9 +1883,7 @@ export type SessionMessageAssistantTool = { time: { created: number; ran?: number; completed?: number } } -export type FormFields = [FormField, ...Array] - -export type FormFields3 = [FormField1, ...Array] +export type FormFields2 = [FormField1, ...Array] export type SessionInboxInfo = SessionInboxUser | SessionInboxSynthetic | SessionInboxCompaction | SessionInboxMove @@ -1893,6 +1897,14 @@ export type SessionInboxEnqueued = { data: { sessionID: string; inboxID: string; item: SessionInboxItem } } +export type FormField = + | FormStringField + | FormNumberField + | FormIntegerField + | FormBooleanField + | FormMultiselectField + | FormExternalField + export type SessionMessageAssistant = { id: string metadata?: { [x: string]: JsonValue } @@ -1909,13 +1921,7 @@ export type SessionMessageAssistant = { retry?: SessionMessageAssistantRetry } -export type IntegrationOAuthMethod = { id: string; type: "oauth"; label: string; form?: FormFields } - -export type IntegrationKeyMethod = { type: "key"; label?: string; form?: FormFields } - -export type FormInfo = { id: string; sessionID: string; title: string; metadata?: FormMetadata; fields: FormFields } - -export type FormInfo1 = { id: string; sessionID: string; title: string; metadata?: FormMetadata1; fields: FormFields3 } +export type FormInfo1 = { id: string; sessionID: string; title: string; metadata?: FormMetadata1; fields: FormFields2 } export type SessionEventDurable = | SessionCreated @@ -1959,6 +1965,8 @@ export type SessionEventDurable = | SessionRevertCommitted | SessionUsageRecorded +export type FormFields = [FormField, ...Array] + export type SessionMessageInfo = | SessionMessageAgentSelected | SessionMessageModelSelected @@ -1971,12 +1979,6 @@ export type SessionMessageInfo = | SessionMessageAssistant | SessionMessageCompaction -export type IntegrationMethod = - | IntegrationOAuthMethod - | IntegrationCommandMethod - | IntegrationKeyMethod - | IntegrationEnvMethod - export type FormCreated = { id: string created: number @@ -1988,6 +1990,12 @@ export type FormCreated = { export type SessionLogItem = SessionEventDurable | EventLogSynced +export type IntegrationOAuthMethod = { id: string; type: "oauth"; label: string; form?: FormFields } + +export type IntegrationKeyMethod = { type: "key"; label?: string; form?: FormFields } + +export type FormInfo = { id: string; sessionID: string; title: string; metadata?: FormMetadata; fields: FormFields } + export type SessionTransferData = { info: SessionInfo; messages: Array } export type SessionMessagesResponse = { @@ -1995,13 +2003,6 @@ export type SessionMessagesResponse = { cursor: { previous?: string | null; next?: string | null } } -export type IntegrationInfo = { - id: string - name: string - methods: Array - connections: Array -} - export type V2Event = | ModelsDevRefreshed | IntegrationUpdated @@ -2088,6 +2089,19 @@ export type V2Event = | McpResourcesChanged | V2EventServerConnected +export type IntegrationMethod = + | IntegrationOAuthMethod + | IntegrationCommandMethod + | IntegrationKeyMethod + | IntegrationEnvMethod + +export type IntegrationInfo = { + id: string + name: string + methods: Array + connections: Array +} + export type UnauthorizedError = { readonly _tag: "UnauthorizedError"; readonly message: string } export const isUnauthorizedError = (value: unknown): value is UnauthorizedError => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "UnauthorizedError" @@ -4110,7 +4124,7 @@ export type IntegrationOauthConnectOutput = { url: string instructions: string mode: "auto" | "code" - time: { created: number | "Infinity" | "-Infinity" | "NaN"; expires: number | "Infinity" | "-Infinity" | "NaN" } + time: { created: number | ("Infinity" | "-Infinity" | "NaN"); expires: number | ("Infinity" | "-Infinity" | "NaN") } } } @@ -4332,7 +4346,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4356,12 +4370,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4371,12 +4385,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4386,7 +4400,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4399,7 +4413,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4429,7 +4443,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4453,12 +4467,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4468,12 +4482,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4483,7 +4497,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4496,7 +4510,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4533,7 +4547,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4557,12 +4571,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4572,12 +4586,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4587,7 +4601,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4600,7 +4614,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4630,7 +4644,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4654,12 +4668,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4669,12 +4683,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4684,7 +4698,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4697,7 +4711,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4734,7 +4748,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4758,12 +4772,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4773,12 +4787,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4788,7 +4802,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4801,7 +4815,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4831,7 +4845,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4855,12 +4869,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4870,12 +4884,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4885,7 +4899,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -4898,7 +4912,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -4935,7 +4949,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -4959,12 +4973,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4974,12 +4988,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -4989,7 +5003,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -5002,7 +5016,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ @@ -5032,7 +5046,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "string" readonly format?: "email" | "uri" | "date" | "date-time" @@ -5056,12 +5070,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "number" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -5071,12 +5085,12 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "integer" - readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" - readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" - readonly default?: number | "Infinity" | "-Infinity" | "NaN" + readonly minimum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly maximum?: number | ("Infinity" | "-Infinity" | "NaN") + readonly default?: number | ("Infinity" | "-Infinity" | "NaN") } | { readonly key: string @@ -5086,7 +5100,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "boolean" readonly default?: boolean @@ -5099,7 +5113,7 @@ export type FormCreateInput = { readonly when?: ReadonlyArray<{ readonly key: string readonly op: "eq" | "neq" - readonly value: string | number | "Infinity" | "-Infinity" | "NaN" | boolean + readonly value: string | number | ("Infinity" | "-Infinity" | "NaN") | boolean }> readonly type: "multiselect" readonly options: ReadonlyArray<{ diff --git a/packages/codemode/src/openapi/runtime.ts b/packages/codemode/src/openapi/runtime.ts index d64d03e552..1cafd9b515 100644 --- a/packages/codemode/src/openapi/runtime.ts +++ b/packages/codemode/src/openapi/runtime.ts @@ -4,7 +4,7 @@ import { ToolError, toolError } from "../tool-error.js" import { isRecord, own } from "./spec.js" import type { AppliedAuth, Credential, Plan, SecurityScheme } from "./types.js" -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const maxErrorBodyChars = 1_024 const maxResponseBodyBytes = 50 * 1024 * 1024 diff --git a/packages/codemode/src/tool-error.ts b/packages/codemode/src/tool-error.ts index 16460a019a..f61720835b 100644 --- a/packages/codemode/src/tool-error.ts +++ b/packages/codemode/src/tool-error.ts @@ -1,7 +1,7 @@ import { Schema } from "effect" /** Safe operational refusal from a standard tool pack, reported as `ToolFailure`. */ -export class ToolError extends Schema.TaggedErrorClass()("ToolError", { +export class ToolError extends Schema.TaggedError()("ToolError", { message: Schema.String, cause: Schema.optionalKey(Schema.Defect()), }) {} diff --git a/packages/codemode/test/codemode.test.ts b/packages/codemode/test/codemode.test.ts index cac1d46024..3124db57e1 100644 --- a/packages/codemode/test/codemode.test.ts +++ b/packages/codemode/test/codemode.test.ts @@ -5,7 +5,7 @@ import { CodeMode, Tool, toolError } from "../src/index.js" const run = (tool: Tool.Tool) => Effect.runPromise(CodeMode.make({ tools: { host: { call: tool } } }).execute("return await tools.host.call({})")) -class UnsafeHostError extends Schema.TaggedErrorClass()("UnsafeHostError", { +class UnsafeHostError extends Schema.TaggedError()("UnsafeHostError", { reason: Schema.String, }) {} diff --git a/packages/codemode/test/signature.test.ts b/packages/codemode/test/signature.test.ts index 4c29281d47..a4dbd8790a 100644 --- a/packages/codemode/test/signature.test.ts +++ b/packages/codemode/test/signature.test.ts @@ -275,8 +275,10 @@ describe("non-identifier property names render as quoted keys", () => { input: Schema.Struct({ "foo-bar": Schema.String, plain: Schema.optionalKey(Schema.Number) }), execute: () => Effect.succeed(null), }) - expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number }') - expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string,', " plain?: number,", "}"].join("\n")) + expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number | "Infinity" | "-Infinity" | "NaN" }') + expect(inputTypeScript(tool, true)).toBe( + ["{", ' "foo-bar": string,', ' plain?: number | "Infinity" | "-Infinity" | "NaN",', "}"].join("\n"), + ) }) }) diff --git a/packages/core/src/aisdk.ts b/packages/core/src/aisdk.ts index 77c5f111f8..24d2d57860 100644 --- a/packages/core/src/aisdk.ts +++ b/packages/core/src/aisdk.ts @@ -43,6 +43,8 @@ type UserContent = Extract["content"] type AssistantContent = Extract["content"] type ToolResultContent = Extract +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) + export interface SDKEvent { readonly model: Info readonly package: string @@ -146,7 +148,7 @@ function prepareOptions(model: Info, pkg: string) { } if (typeof opts.body === "string" && model.body !== undefined) { - const decoded = Option.getOrUndefined(Schema.decodeUnknownOption(Schema.UnknownFromJsonString)(opts.body)) + const decoded = Option.getOrUndefined(decodeJson(opts.body)) if (Schema.is(Schema.Record(Schema.String, Schema.Json))(decoded)) { opts.body = JSON.stringify(Provider.mergeOverlay(decoded, model.body)) } @@ -163,7 +165,7 @@ function prepareOptions(model: Info, pkg: string) { return options } -export class InitError extends Schema.TaggedErrorClass()("AISDK.InitError", { +export class InitError extends Schema.TaggedError()("AISDK.InitError", { providerID: Provider.ID, cause: Schema.Defect(), }) {} diff --git a/packages/core/src/bus.ts b/packages/core/src/bus.ts index c432c730cc..837b5a4df5 100644 --- a/packages/core/src/bus.ts +++ b/packages/core/src/bus.ts @@ -53,7 +53,7 @@ export type SerializedEvent = { readonly data: Record } -export class InvalidDurableEventError extends Schema.TaggedErrorClass()( +export class InvalidDurableEventError extends Schema.TaggedError()( "Bus.InvalidDurableEvent", { type: Schema.String, diff --git a/packages/core/src/command.ts b/packages/core/src/command.ts index 5197e51a15..bc8f9bbc6f 100644 --- a/packages/core/src/command.ts +++ b/packages/core/src/command.ts @@ -25,12 +25,12 @@ export type Data = { commands: Map> } -export class NotFoundError extends Schema.TaggedErrorClass()("Command.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Command.NotFoundError", { command: Schema.String, message: Schema.String, }) {} -export class EvaluationError extends Schema.TaggedErrorClass()("Command.EvaluationError", { +export class EvaluationError extends Schema.TaggedError()("Command.EvaluationError", { command: Schema.String, message: Schema.String, }) {} diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 6f2b402cea..8a12e5b6dc 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -47,7 +47,7 @@ export interface Interface { readonly changes: () => Stream.Stream } -export class UpdateError extends Schema.TaggedErrorClass()("Config.UpdateError", { +export class UpdateError extends Schema.TaggedError()("Config.UpdateError", { message: Schema.String, cause: Schema.optional(Schema.Defect()), }) {} diff --git a/packages/core/src/database/migration/20260805200742_import_legacy_credentials.ts b/packages/core/src/database/migration/20260805200742_import_legacy_credentials.ts index f109c2ab2e..01950cf4e9 100644 --- a/packages/core/src/database/migration/20260805200742_import_legacy_credentials.ts +++ b/packages/core/src/database/migration/20260805200742_import_legacy_credentials.ts @@ -27,7 +27,7 @@ const LegacyWellKnown = Schema.Struct({ token: Schema.String, }) const LegacyValue = Schema.Union([LegacyOAuth, LegacyKey, LegacyWellKnown]) -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const decodeValue = Schema.decodeUnknownOption(LegacyValue) const wellKnownSourcesKey = "wellknown:sources" diff --git a/packages/core/src/database/v1-migration.bun.ts b/packages/core/src/database/v1-migration.bun.ts index 5c3150c77c..537b91bad6 100644 --- a/packages/core/src/database/v1-migration.bun.ts +++ b/packages/core/src/database/v1-migration.bun.ts @@ -162,7 +162,7 @@ type NextMessage = { const lock = Semaphore.makeUnsafe(1) const MIGRATION_STATE_KEY = "migration.v1-v2" const EVENT_DELETE_BATCH_SIZE = 1_000 -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const decodeMessage = Schema.decodeUnknownOption(SessionV1.Info) const decodePart = Schema.decodeUnknownOption(SessionV1.Part) let runtimeState: RuntimeState = { status: "idle" } diff --git a/packages/core/src/environment/files.ts b/packages/core/src/environment/files.ts index 0029fb2849..39c9bf2f3b 100644 --- a/packages/core/src/environment/files.ts +++ b/packages/core/src/environment/files.ts @@ -14,16 +14,16 @@ export interface DirEntry { readonly type: FileType } -export class NotFound extends Schema.TaggedErrorClass()("Environment.NotFound", { +export class NotFound extends Schema.TaggedError()("Environment.NotFound", { path: Schema.String, }) {} -export class WrongKind extends Schema.TaggedErrorClass()("Environment.WrongKind", { +export class WrongKind extends Schema.TaggedError()("Environment.WrongKind", { path: Schema.String, actual: FileType, }) {} -export class Failed extends Schema.TaggedErrorClass()("Environment.Failed", { +export class Failed extends Schema.TaggedError()("Environment.Failed", { path: Schema.String, cause: Schema.Defect(), }) {} diff --git a/packages/core/src/form.ts b/packages/core/src/form.ts index e2f21c094e..b8098733e3 100644 --- a/packages/core/src/form.ts +++ b/packages/core/src/form.ts @@ -34,7 +34,7 @@ export type Reply = typeof Reply.Type export { Event } from "@opencode-ai/schema/form" -export class NotFoundError extends Schema.TaggedErrorClass()("Form.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Form.NotFoundError", { id: ID, }) { override get message() { @@ -42,7 +42,7 @@ export class NotFoundError extends Schema.TaggedErrorClass()("For } } -export class AlreadySettledError extends Schema.TaggedErrorClass()("Form.AlreadySettledError", { +export class AlreadySettledError extends Schema.TaggedError()("Form.AlreadySettledError", { id: ID, }) { override get message() { @@ -50,7 +50,7 @@ export class AlreadySettledError extends Schema.TaggedErrorClass()("Form.AlreadyExistsError", { +export class AlreadyExistsError extends Schema.TaggedError()("Form.AlreadyExistsError", { id: ID, }) { override get message() { @@ -58,12 +58,12 @@ export class AlreadyExistsError extends Schema.TaggedErrorClass()("Form.InvalidAnswerError", { +export class InvalidAnswerError extends Schema.TaggedError()("Form.InvalidAnswerError", { id: ID, message: Schema.String, }) {} -export class InvalidFormError extends Schema.TaggedErrorClass()("Form.InvalidFormError", { +export class InvalidFormError extends Schema.TaggedError()("Form.InvalidFormError", { message: Schema.String, }) {} diff --git a/packages/core/src/generate.ts b/packages/core/src/generate.ts index d14c2eb952..8e2f1a0df6 100644 --- a/packages/core/src/generate.ts +++ b/packages/core/src/generate.ts @@ -12,12 +12,12 @@ export interface TextInput { readonly model?: Model.Ref } -export class ModelSelectionError extends Schema.TaggedErrorClass()( +export class ModelSelectionError extends Schema.TaggedError()( "Generate.ModelSelectionError", { message: Schema.String }, ) {} -export class UnavailableError extends Schema.TaggedErrorClass()("Generate.UnavailableError", { +export class UnavailableError extends Schema.TaggedError()("Generate.UnavailableError", { message: Schema.String, service: Schema.optional(Schema.String), }) {} diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts index 07fb81b6ca..aedcade5bf 100644 --- a/packages/core/src/git.ts +++ b/packages/core/src/git.ts @@ -38,7 +38,7 @@ const snapshotConfig = `[core] export const TreeID = Schema.String.pipe(Schema.brand("Git.TreeID")) export type TreeID = typeof TreeID.Type -export class OperationError extends Schema.TaggedErrorClass()("Git.OperationError", { +export class OperationError extends Schema.TaggedError()("Git.OperationError", { operation: Schema.Literals([ "clone", "fetch", @@ -61,7 +61,7 @@ export class Worktree extends Schema.Class("Git.Worktree")({ kind: Schema.Literals(["main", "linked"]), }) {} -export class WorktreeError extends Schema.TaggedErrorClass()("Git.WorktreeError", { +export class WorktreeError extends Schema.TaggedError()("Git.WorktreeError", { operation: Schema.Literals(["create", "remove", "list"]), message: Schema.String, directory: Schema.optional(AbsolutePath), diff --git a/packages/core/src/image.ts b/packages/core/src/image.ts index afcbe00cdb..2325dcb417 100644 --- a/packages/core/src/image.ts +++ b/packages/core/src/image.ts @@ -5,12 +5,12 @@ import { Context, Effect, Layer, Schema } from "effect" import { Config } from "./config.js" import { FileSystem } from "./filesystem.js" -export class ResizerUnavailableError extends Schema.TaggedErrorClass()( +export class ResizerUnavailableError extends Schema.TaggedError()( "Image.ResizerUnavailableError", {}, ) {} -export class DecodeError extends Schema.TaggedErrorClass()("Image.DecodeError", { +export class DecodeError extends Schema.TaggedError()("Image.DecodeError", { resource: Schema.String, }) { override get message() { @@ -18,7 +18,7 @@ export class DecodeError extends Schema.TaggedErrorClass()("Image.D } } -export class SizeError extends Schema.TaggedErrorClass()("Image.SizeError", { +export class SizeError extends Schema.TaggedError()("Image.SizeError", { resource: Schema.String, width: Schema.Number, height: Schema.Number, diff --git a/packages/core/src/instructions/index.ts b/packages/core/src/instructions/index.ts index bafb069c27..27e1d2a650 100644 --- a/packages/core/src/instructions/index.ts +++ b/packages/core/src/instructions/index.ts @@ -65,7 +65,7 @@ export interface Admission { readonly blobs: Readonly> } -export class InitializationBlocked extends Schema.TaggedErrorClass()( +export class InitializationBlocked extends Schema.TaggedError()( "Instructions.InitializationBlocked", { keys: Schema.Array(Key) }, ) { @@ -74,7 +74,7 @@ export class InitializationBlocked extends Schema.TaggedErrorClass()("Instructions.DuplicateKeyError", { +export class DuplicateKeyError extends Schema.TaggedError()("Instructions.DuplicateKeyError", { key: Key, }) { override get message() { diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index ef740a71c6..0c25bcd223 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -105,11 +105,11 @@ export type CommandAttempt = Integration.CommandAttempt export const CommandAttemptStatus = Integration.CommandAttemptStatus export type CommandAttemptStatus = Integration.CommandAttemptStatus -export class CodeRequiredError extends Schema.TaggedErrorClass()("Integration.CodeRequired", { +export class CodeRequiredError extends Schema.TaggedError()("Integration.CodeRequired", { attemptID: AttemptID, }) {} -export class AuthorizationError extends Schema.TaggedErrorClass()("Integration.Authorization", { +export class AuthorizationError extends Schema.TaggedError()("Integration.Authorization", { cause: Schema.Defect(), }) {} diff --git a/packages/core/src/mcp/client.ts b/packages/core/src/mcp/client.ts index b5cba91ff8..31021eed19 100644 --- a/packages/core/src/mcp/client.ts +++ b/packages/core/src/mcp/client.ts @@ -44,7 +44,7 @@ const TolerantListPromptsResult = ListPromptsResultSchema.extend({ prompts: PromptSchema.array(), }) -export class NeedsAuthError extends Schema.TaggedErrorClass()("MCP.NeedsAuthError", { +export class NeedsAuthError extends Schema.TaggedError()("MCP.NeedsAuthError", { server: Schema.String, }) { override get message() { @@ -52,7 +52,7 @@ export class NeedsAuthError extends Schema.TaggedErrorClass()("M } } -export class ConnectError extends Schema.TaggedErrorClass()("MCP.ConnectError", { +export class ConnectError extends Schema.TaggedError()("MCP.ConnectError", { server: Schema.String, message: Schema.String, }) {} diff --git a/packages/core/src/mcp/index.ts b/packages/core/src/mcp/index.ts index e087c36b29..dca10bdd4c 100644 --- a/packages/core/src/mcp/index.ts +++ b/packages/core/src/mcp/index.ts @@ -97,7 +97,7 @@ export type ResourceContentPart = Mcp.ResourceContentPart export const ResourceContent = Mcp.ResourceContent export type ResourceContent = Mcp.ResourceContent -export class NotFoundError extends Schema.TaggedErrorClass()("MCP.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("MCP.NotFoundError", { server: ServerName, }) { override get message() { @@ -105,7 +105,7 @@ export class NotFoundError extends Schema.TaggedErrorClass()("MCP } } -export class ToolCallError extends Schema.TaggedErrorClass()("MCP.ToolCallError", { +export class ToolCallError extends Schema.TaggedError()("MCP.ToolCallError", { server: ServerName, tool: Schema.String, message: Schema.String, diff --git a/packages/core/src/model-resolver.ts b/packages/core/src/model-resolver.ts index 05f8747760..d8c6c063bf 100644 --- a/packages/core/src/model-resolver.ts +++ b/packages/core/src/model-resolver.ts @@ -20,7 +20,7 @@ import { Capabilities, ID, Info, Ref, VariantID } from "./model.js" import { Npm } from "@opencode-ai/util/npm" import { Provider } from "./provider.js" -export class VariantUnavailableError extends Schema.TaggedErrorClass()( +export class VariantUnavailableError extends Schema.TaggedError()( "SessionRunnerModel.VariantUnavailableError", { providerID: Provider.ID, @@ -33,7 +33,7 @@ export class VariantUnavailableError extends Schema.TaggedErrorClass()( +export class UnsupportedPackageError extends Schema.TaggedError()( "SessionRunnerModel.UnsupportedPackageError", { providerID: Provider.ID, @@ -46,7 +46,7 @@ export class UnsupportedPackageError extends Schema.TaggedErrorClass()( +export class UnresolvedProviderVariablesError extends Schema.TaggedError()( "SessionRunnerModel.UnresolvedProviderVariablesError", { providerID: Provider.ID, diff --git a/packages/core/src/permission.ts b/packages/core/src/permission.ts index d7c6bf34ea..582fa44ced 100644 --- a/packages/core/src/permission.ts +++ b/packages/core/src/permission.ts @@ -60,13 +60,13 @@ export type AskResult = typeof AskResult.Type export { Event } from "@opencode-ai/schema/permission" -export class DeclinedError extends Schema.TaggedErrorClass()("Permission.DeclinedError", {}) {} +export class DeclinedError extends Schema.TaggedError()("Permission.DeclinedError", {}) {} -export class CorrectedError extends Schema.TaggedErrorClass()("Permission.CorrectedError", { +export class CorrectedError extends Schema.TaggedError()("Permission.CorrectedError", { feedback: Schema.String, }) {} -export class BlockedError extends Schema.TaggedErrorClass()("Permission.BlockedError", { +export class BlockedError extends Schema.TaggedError()("Permission.BlockedError", { rules: Permission.Ruleset, permission: Schema.String, resources: Schema.Array(Schema.String), @@ -76,7 +76,7 @@ export class BlockedError extends Schema.TaggedErrorClass()("Permi } } -export class NotFoundError extends Schema.TaggedErrorClass()("Permission.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Permission.NotFoundError", { requestID: ID, }) {} diff --git a/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts b/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts index e23249d843..491ce64baf 100644 --- a/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts +++ b/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts @@ -85,7 +85,7 @@ type GatewayConfig = { apiKey: string } -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) function gatewayConfig(options: Record): GatewayConfig | undefined { const accountId = process.env.CLOUDFLARE_ACCOUNT_ID ?? stringOption(options, "accountId") diff --git a/packages/core/src/plugin/provider/github-copilot.ts b/packages/core/src/plugin/provider/github-copilot.ts index 916c0b922f..7b9245f92d 100644 --- a/packages/core/src/plugin/provider/github-copilot.ts +++ b/packages/core/src/plugin/provider/github-copilot.ts @@ -37,7 +37,7 @@ const User = Schema.Struct({ ), }) const decodeUser = Schema.decodeUnknownOption(User) -const JsonBody = Schema.UnknownFromJsonString +const JsonBody = Schema.fromJsonString(Schema.Unknown) const decodeBody = Schema.decodeUnknownOption(JsonBody) const oauth = (app: App.Info) => diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts index 0eaa31f155..70b1df53e3 100644 --- a/packages/core/src/provider.ts +++ b/packages/core/src/provider.ts @@ -25,7 +25,7 @@ type Json = Schema.Schema.Type const JsonRecord = Schema.Record(Schema.String, Schema.Json) const decodeJsonRecord = Schema.decodeUnknownSync(JsonRecord) -export class LoadError extends Schema.TaggedErrorClass()("Provider.LoadError", { +export class LoadError extends Schema.TaggedError()("Provider.LoadError", { package: Schema.String, cause: Schema.Defect(), }) {} diff --git a/packages/core/src/pty.ts b/packages/core/src/pty.ts index 83315bcbfc..10ac3acdf6 100644 --- a/packages/core/src/pty.ts +++ b/packages/core/src/pty.ts @@ -70,11 +70,11 @@ export type Attachment = { readonly detach: () => void } -export class NotFoundError extends Schema.TaggedErrorClass()("Pty.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Pty.NotFoundError", { ptyID: PtyID, }) {} -export class ExitedError extends Schema.TaggedErrorClass()("Pty.ExitedError", { +export class ExitedError extends Schema.TaggedError()("Pty.ExitedError", { ptyID: PtyID, }) {} diff --git a/packages/core/src/repository-cache.ts b/packages/core/src/repository-cache.ts index 867ccd74ea..f3fdabeee7 100644 --- a/packages/core/src/repository-cache.ts +++ b/packages/core/src/repository-cache.ts @@ -31,7 +31,7 @@ export type EnsureInput = { readonly branch?: string } -export class InvalidBranchError extends Schema.TaggedErrorClass()( +export class InvalidBranchError extends Schema.TaggedError()( "RepositoryCacheInvalidBranchError", { branch: Schema.String, @@ -39,17 +39,17 @@ export class InvalidBranchError extends Schema.TaggedErrorClass()("RepositoryCacheCloneFailedError", { +export class CloneFailedError extends Schema.TaggedError()("RepositoryCacheCloneFailedError", { repository: Schema.String, message: Schema.String, }) {} -export class FetchFailedError extends Schema.TaggedErrorClass()("RepositoryCacheFetchFailedError", { +export class FetchFailedError extends Schema.TaggedError()("RepositoryCacheFetchFailedError", { repository: Schema.String, message: Schema.String, }) {} -export class CheckoutFailedError extends Schema.TaggedErrorClass()( +export class CheckoutFailedError extends Schema.TaggedError()( "RepositoryCacheCheckoutFailedError", { repository: Schema.String, @@ -58,17 +58,17 @@ export class CheckoutFailedError extends Schema.TaggedErrorClass()("RepositoryCacheResetFailedError", { +export class ResetFailedError extends Schema.TaggedError()("RepositoryCacheResetFailedError", { repository: Schema.String, message: Schema.String, }) {} -export class LockFailedError extends Schema.TaggedErrorClass()("RepositoryCacheLockFailedError", { +export class LockFailedError extends Schema.TaggedError()("RepositoryCacheLockFailedError", { localPath: Schema.String, message: Schema.String, }) {} -export class CacheOperationError extends Schema.TaggedErrorClass()( +export class CacheOperationError extends Schema.TaggedError()( "RepositoryCacheOperationError", { operation: Schema.String, diff --git a/packages/core/src/repository.ts b/packages/core/src/repository.ts index 6de2737a28..3f14477d45 100644 --- a/packages/core/src/repository.ts +++ b/packages/core/src/repository.ts @@ -23,7 +23,7 @@ export type FileReference = BaseReference & { export type Reference = RemoteReference | FileReference -export class InvalidReferenceError extends Schema.TaggedErrorClass()( +export class InvalidReferenceError extends Schema.TaggedError()( "RepositoryInvalidReferenceError", { repository: Schema.String, @@ -31,7 +31,7 @@ export class InvalidReferenceError extends Schema.TaggedErrorClass()( +export class UnsupportedLocalRepositoryError extends Schema.TaggedError()( "RepositoryUnsupportedLocalRepositoryError", { repository: Schema.String, @@ -39,7 +39,7 @@ export class UnsupportedLocalRepositoryError extends Schema.TaggedErrorClass()("RepositoryInvalidBranchError", { +export class InvalidBranchError extends Schema.TaggedError()("RepositoryInvalidBranchError", { branch: Schema.String, message: Schema.String, }) {} diff --git a/packages/core/src/ripgrep.ts b/packages/core/src/ripgrep.ts index 44f8a67fe3..1e029f7b5b 100644 --- a/packages/core/src/ripgrep.ts +++ b/packages/core/src/ripgrep.ts @@ -35,16 +35,16 @@ const RawMatch = Schema.Struct({ ), }), }) -const decodeJsonRecord = Schema.decodeUnknownEffect(Schema.UnknownFromJsonString) +const decodeJsonRecord = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown)) type RawMatchData = (typeof RawMatch.Type)["data"] -export class Error extends Schema.TaggedErrorClass()("Ripgrep.Error", { +export class Error extends Schema.TaggedError()("Ripgrep.Error", { message: Schema.String, cause: Schema.optional(Schema.Defect()), }) {} -export class InvalidPatternError extends Schema.TaggedErrorClass()("Ripgrep.InvalidPatternError", { +export class InvalidPatternError extends Schema.TaggedError()("Ripgrep.InvalidPatternError", { pattern: Schema.String, message: Schema.String, }) {} diff --git a/packages/core/src/schema.ts b/packages/core/src/schema.ts index 338255309f..19796c4dfd 100644 --- a/packages/core/src/schema.ts +++ b/packages/core/src/schema.ts @@ -58,7 +58,7 @@ export type DeepMutable = T extends string | number | boolean | bigint | symb type NewtypeSchema = (abstract new (_: never) => { readonly _newtype: Tag }) & - Schema.Bottom< + Schema.BottomWithoutNew< Self, S["Encoded"], S["DecodingServices"], diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index 3ecf02305e..4cd2634961 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -111,46 +111,46 @@ type ForkInput = { export { MessageDecodeError, NotFoundError } -export class PromptConflictError extends Schema.TaggedErrorClass()("Session.PromptConflictError", { +export class PromptConflictError extends Schema.TaggedError()("Session.PromptConflictError", { sessionID: SessionSchema.ID, messageID: SessionMessage.ID, }) {} -export class SyntheticConflictError extends Schema.TaggedErrorClass()( +export class SyntheticConflictError extends Schema.TaggedError()( "Session.SyntheticConflictError", { sessionID: SessionSchema.ID, inputID: SessionMessage.ID, }, ) {} -export class AttachmentError extends Schema.TaggedErrorClass()("Session.AttachmentError", { +export class AttachmentError extends Schema.TaggedError()("Session.AttachmentError", { uri: Schema.String, message: Schema.String, }) {} -export class CompactionConflictError extends Schema.TaggedErrorClass()( +export class CompactionConflictError extends Schema.TaggedError()( "Session.CompactionConflictError", { sessionID: SessionSchema.ID, inputID: SessionMessage.ID, }, ) {} -export class BusyError extends Schema.TaggedErrorClass()("Session.BusyError", { +export class BusyError extends Schema.TaggedError()("Session.BusyError", { sessionID: SessionSchema.ID, }) {} -export class InboxConflictError extends Schema.TaggedErrorClass()("Session.InboxConflictError", { +export class InboxConflictError extends Schema.TaggedError()("Session.InboxConflictError", { sessionID: SessionSchema.ID, inboxID: SessionMessage.ID, }) {} type InboxItemRef = { readonly sessionID: SessionSchema.ID; readonly inboxID: SessionMessage.ID } -export class SkillNotFoundError extends Schema.TaggedErrorClass()("Session.SkillNotFoundError", { +export class SkillNotFoundError extends Schema.TaggedError()("Session.SkillNotFoundError", { skill: Skill.ID, }) {} -export class DestinationNotFoundError extends Schema.TaggedErrorClass()( +export class DestinationNotFoundError extends Schema.TaggedError()( "Session.DestinationNotFoundError", { directory: AbsolutePath }, ) {} -export class DestinationNotDirectoryError extends Schema.TaggedErrorClass()( +export class DestinationNotDirectoryError extends Schema.TaggedError()( "Session.DestinationNotDirectoryError", { directory: AbsolutePath }, ) {} diff --git a/packages/core/src/session/error.ts b/packages/core/src/session/error.ts index 7db21c5697..969111eff1 100644 --- a/packages/core/src/session/error.ts +++ b/packages/core/src/session/error.ts @@ -6,11 +6,11 @@ import { SessionMessage } from "./message.js" import { SessionSchema } from "./schema.js" import { SessionError } from "@opencode-ai/schema/session-error" -export class NotFoundError extends Schema.TaggedErrorClass()("Session.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Session.NotFoundError", { sessionID: SessionSchema.ID, }) {} -export class ForkEmptyError extends Schema.TaggedErrorClass()("Session.ForkEmptyError", { +export class ForkEmptyError extends Schema.TaggedError()("Session.ForkEmptyError", { sessionID: SessionSchema.ID, }) { override get message() { @@ -18,7 +18,7 @@ export class ForkEmptyError extends Schema.TaggedErrorClass()("S } } -export class MessageDecodeError extends Schema.TaggedErrorClass()("Session.MessageDecodeError", { +export class MessageDecodeError extends Schema.TaggedError()("Session.MessageDecodeError", { sessionID: SessionSchema.ID, messageID: SessionMessage.ID, }) { @@ -27,7 +27,7 @@ export class MessageDecodeError extends Schema.TaggedErrorClass()("Session.AgentNotFoundError", { +export class AgentNotFoundError extends Schema.TaggedError()("Session.AgentNotFoundError", { sessionID: SessionSchema.ID, agent: Agent.ID, }) { @@ -36,7 +36,7 @@ export class AgentNotFoundError extends Schema.TaggedErrorClass()("Session.StepFailedError", { +export class StepFailedError extends Schema.TaggedError()("Session.StepFailedError", { error: SessionError.Error, }) { override get message() { @@ -44,7 +44,7 @@ export class StepFailedError extends Schema.TaggedErrorClass()( } } -export class UserInterruptedError extends Schema.TaggedErrorClass()( +export class UserInterruptedError extends Schema.TaggedError()( "Session.UserInterruptedError", {}, ) { diff --git a/packages/core/src/session/inbox.ts b/packages/core/src/session/inbox.ts index a0d1f3ef57..1233ebf685 100644 --- a/packages/core/src/session/inbox.ts +++ b/packages/core/src/session/inbox.ts @@ -61,7 +61,7 @@ type PendingRef = { readonly id: SessionMessage.ID; readonly sessionID: SessionS export const serialized = (sessionID: SessionSchema.ID, effect: Effect.Effect) => inboxLocks.withLock(sessionID)(effect) -export class LifecycleConflict extends Schema.TaggedErrorClass()("SessionInbox.LifecycleConflict", { +export class LifecycleConflict extends Schema.TaggedError()("SessionInbox.LifecycleConflict", { id: SessionMessage.ID, }) {} diff --git a/packages/core/src/session/revert.ts b/packages/core/src/session/revert.ts index d0f080fc75..675986367c 100644 --- a/packages/core/src/session/revert.ts +++ b/packages/core/src/session/revert.ts @@ -11,7 +11,7 @@ import { SessionMessage } from "./message.js" import { SessionSchema } from "./schema.js" import { SessionMessageTable } from "./sql.js" -export class MessageNotFoundError extends Schema.TaggedErrorClass()( +export class MessageNotFoundError extends Schema.TaggedError()( "Session.MessageNotFoundError", { sessionID: SessionSchema.ID, diff --git a/packages/core/src/session/runner/model.ts b/packages/core/src/session/runner/model.ts index 98e1983fcd..00205e716c 100644 --- a/packages/core/src/session/runner/model.ts +++ b/packages/core/src/session/runner/model.ts @@ -9,7 +9,7 @@ import { Capabilities, ID, Info, Ref, VariantID } from "../../model.js" import { Provider } from "../../provider.js" import { SessionSchema } from "../schema.js" -export class ModelNotSelectedError extends Schema.TaggedErrorClass()( +export class ModelNotSelectedError extends Schema.TaggedError()( "SessionRunnerModel.ModelNotSelectedError", { sessionID: SessionSchema.ID }, ) { @@ -18,7 +18,7 @@ export class ModelNotSelectedError extends Schema.TaggedErrorClass()( +export class ModelUnavailableError extends Schema.TaggedError()( "SessionRunnerModel.ModelUnavailableError", { providerID: Provider.ID, modelID: ID }, ) { diff --git a/packages/core/src/session/runner/to-llm-message.ts b/packages/core/src/session/runner/to-llm-message.ts index 967f56bedc..f84b3a0209 100644 --- a/packages/core/src/session/runner/to-llm-message.ts +++ b/packages/core/src/session/runner/to-llm-message.ts @@ -93,7 +93,7 @@ const userAttachmentContent = (files: readonly FileAttachment[]) => { }) } -const decodeToolInput = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeToolInput = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const providerMetadata = ( provider: string, diff --git a/packages/core/src/session/transfer.ts b/packages/core/src/session/transfer.ts index 92a3f12182..6682e5051e 100644 --- a/packages/core/src/session/transfer.ts +++ b/packages/core/src/session/transfer.ts @@ -24,7 +24,7 @@ import { SessionMessageTable, SessionTable } from "./sql.js" export const Data = SessionTransfer.Data export type Data = SessionTransfer.Data -export class ImportConflictError extends Schema.TaggedErrorClass()( +export class ImportConflictError extends Schema.TaggedError()( "SessionTransfer.ImportConflictError", { sessionID: Session.ID }, ) {} diff --git a/packages/core/src/shell.ts b/packages/core/src/shell.ts index a2d52893ff..3b3d2dc67f 100644 --- a/packages/core/src/shell.ts +++ b/packages/core/src/shell.ts @@ -18,7 +18,7 @@ import { PluginHooks } from "./plugin/hooks.js" import { SessionEnvironment } from "./session/environment.js" import { SessionSchema } from "./session/schema.js" -export class NotFoundError extends Schema.TaggedErrorClass()("Shell.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Shell.NotFoundError", { id: Shell.ID, }) {} diff --git a/packages/core/src/snapshot.ts b/packages/core/src/snapshot.ts index 15e21c831d..044b0c7e09 100644 --- a/packages/core/src/snapshot.ts +++ b/packages/core/src/snapshot.ts @@ -15,7 +15,7 @@ import { Hash } from "@opencode-ai/util/hash" export { ID } -export class Error extends Schema.TaggedErrorClass()("Snapshot.Error", { +export class Error extends Schema.TaggedError()("Snapshot.Error", { operation: Schema.Literals(["capture", "files", "diff", "restore"]), message: Schema.String, cause: Schema.optional(Schema.Defect()), diff --git a/packages/core/src/tool.ts b/packages/core/src/tool.ts index 218580f52b..a98f79f529 100644 --- a/packages/core/src/tool.ts +++ b/packages/core/src/tool.ts @@ -4,7 +4,7 @@ export type { Context, Metadata, Options, Result } from "@opencode-ai/schema/too import { ToolDefinition, type ToolCall } from "@opencode-ai/ai" import { Tool } from "@opencode-ai/schema/tool" -import { Context, Effect, Layer, Schema, Scope, Semaphore } from "effect" +import { Context, Effect, Layer, Schema, SchemaIssue, Scope, Semaphore } from "effect" import { makeLocationNode } from "@opencode-ai/util/effect/app-node" import type { Agent } from "./agent.js" import { CodeModeCatalog } from "./codemode/catalog.js" @@ -17,7 +17,7 @@ import { SessionSchema } from "./session/schema.js" import { definition, execute, normalizeContent } from "./tool/runtime.js" import { Wildcard } from "./util/wildcard.js" -export class RegistrationError extends Schema.TaggedErrorClass()("Tool.RegistrationError", { +export class RegistrationError extends Schema.TaggedError()("Tool.RegistrationError", { name: Schema.String, message: Schema.String, }) {} @@ -173,7 +173,7 @@ const layer = Layer.effect( catch: (error) => new RegistrationError({ name: entry.key, - message: `Invalid tool definition ${entry.key}: ${error instanceof Error ? error.message : String(error)}`, + message: `Invalid tool definition ${entry.key}: ${schemaMakeError(error)}`, }), }), { discard: true }, @@ -262,6 +262,13 @@ const whollyDisabled = (action: string, rules: Permission.Ruleset) => { return rule?.resource === "*" && rule.effect === "deny" } +const formatSchemaIssue = SchemaIssue.makeFormatterDefault() + +function schemaMakeError(error: unknown) { + if (error instanceof Error && SchemaIssue.isIssue(error.cause)) return formatSchemaIssue(error.cause) + return error instanceof Error ? error.message : String(error) +} + const validateName = (name: string) => /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(name) ? Effect.void diff --git a/packages/core/src/tool/plugin/question.ts b/packages/core/src/tool/plugin/question.ts index 26e8274152..72404199f4 100644 --- a/packages/core/src/tool/plugin/question.ts +++ b/packages/core/src/tool/plugin/question.ts @@ -29,7 +29,7 @@ export const Output = Schema.Struct({ }) export type Output = typeof Output.Type -export class CancelledError extends Schema.TaggedErrorClass()("QuestionTool.CancelledError", {}) { +export class CancelledError extends Schema.TaggedError()("QuestionTool.CancelledError", {}) { override get message() { return "The user dismissed this question" } diff --git a/packages/core/src/tool/read-filesystem.ts b/packages/core/src/tool/read-filesystem.ts index 4307d83ad0..8a7c1a58d5 100644 --- a/packages/core/src/tool/read-filesystem.ts +++ b/packages/core/src/tool/read-filesystem.ts @@ -19,7 +19,7 @@ const MAX_LINE_LENGTH = 2_000 const MAX_LINE_SUFFIX = `... (line truncated to ${MAX_LINE_LENGTH} chars)` const MEDIA_MIMES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp", "application/pdf"]) -export class BinaryFileError extends Schema.TaggedErrorClass()("ReadTool.BinaryFileError", { +export class BinaryFileError extends Schema.TaggedError()("ReadTool.BinaryFileError", { resource: Schema.String, }) { override get message() { @@ -27,7 +27,7 @@ export class BinaryFileError extends Schema.TaggedErrorClass()( } } -export class MediaIngestLimitError extends Schema.TaggedErrorClass()( +export class MediaIngestLimitError extends Schema.TaggedError()( "ReadTool.MediaIngestLimitError", { resource: Schema.String, @@ -39,7 +39,7 @@ export class MediaIngestLimitError extends Schema.TaggedErrorClass()( +export class OffsetOutOfRangeError extends Schema.TaggedError()( "ReadTool.OffsetOutOfRangeError", { offset: Schema.Number }, ) { @@ -48,7 +48,7 @@ export class OffsetOutOfRangeError extends Schema.TaggedErrorClass()("ReadTool.PathKindError", { +export class PathKindError extends Schema.TaggedError()("ReadTool.PathKindError", { resource: Schema.String, expected: Schema.Literals(["a file", "a file or directory"]), }) { diff --git a/packages/core/src/util/process-lock.ts b/packages/core/src/util/process-lock.ts index 196ed8a337..414c1542a6 100644 --- a/packages/core/src/util/process-lock.ts +++ b/packages/core/src/util/process-lock.ts @@ -6,7 +6,7 @@ import { Effect, Schema } from "effect" import { Hash } from "@opencode-ai/util/hash" export namespace ProcessLock { - export class HeldError extends Schema.TaggedErrorClass()("ProcessLockHeldError", { + export class HeldError extends Schema.TaggedError()("ProcessLockHeldError", { file: Schema.String, }) { override get message() { @@ -14,7 +14,7 @@ export namespace ProcessLock { } } - export class SystemError extends Schema.TaggedErrorClass()("ProcessLockSystemError", { + export class SystemError extends Schema.TaggedError()("ProcessLockSystemError", { file: Schema.String, operation: Schema.Literals(["open", "acquire"]), code: Schema.String, diff --git a/packages/core/src/v1/permission.ts b/packages/core/src/v1/permission.ts index aa35187c09..0e8ea590a9 100644 --- a/packages/core/src/v1/permission.ts +++ b/packages/core/src/v1/permission.ts @@ -4,13 +4,13 @@ import { Schema } from "effect" export * from "@opencode-ai/schema/permission-v1" import { ID } from "@opencode-ai/schema/permission-v1" -export class RejectedError extends Schema.TaggedErrorClass()("PermissionRejectedError", {}) { +export class RejectedError extends Schema.TaggedError()("PermissionRejectedError", {}) { override get message() { return "The user rejected permission to use this specific tool call." } } -export class CorrectedError extends Schema.TaggedErrorClass()("PermissionCorrectedError", { +export class CorrectedError extends Schema.TaggedError()("PermissionCorrectedError", { feedback: Schema.String, }) { override get message() { @@ -18,7 +18,7 @@ export class CorrectedError extends Schema.TaggedErrorClass()("P } } -export class DeniedError extends Schema.TaggedErrorClass()("PermissionDeniedError", { +export class DeniedError extends Schema.TaggedError()("PermissionDeniedError", { ruleset: Schema.Any, }) { override get message() { @@ -26,7 +26,7 @@ export class DeniedError extends Schema.TaggedErrorClass()("Permiss } } -export class NotFoundError extends Schema.TaggedErrorClass()("Permission.NotFoundError", { +export class NotFoundError extends Schema.TaggedError()("Permission.NotFoundError", { requestID: ID, }) {} diff --git a/packages/core/src/websearch.ts b/packages/core/src/websearch.ts index e23edffab6..c790410356 100644 --- a/packages/core/src/websearch.ts +++ b/packages/core/src/websearch.ts @@ -28,21 +28,21 @@ export interface ProviderImplementation extends Provider { readonly execute: (input: ProviderInput) => Effect.Effect } -export class ProviderRequiredError extends Schema.TaggedErrorClass()( +export class ProviderRequiredError extends Schema.TaggedError()( "WebSearch.ProviderRequired", {}, ) {} -export class ProviderNotFoundError extends Schema.TaggedErrorClass()( +export class ProviderNotFoundError extends Schema.TaggedError()( "WebSearch.ProviderNotFound", { providerID: ID, }, ) {} -export class DisabledError extends Schema.TaggedErrorClass()("WebSearch.Disabled", {}) {} +export class DisabledError extends Schema.TaggedError()("WebSearch.Disabled", {}) {} -export class RequestError extends Schema.TaggedErrorClass()("WebSearch.Request", { +export class RequestError extends Schema.TaggedError()("WebSearch.Request", { providerID: ID, cause: Schema.Defect(), }) {} diff --git a/packages/core/src/workspace.ts b/packages/core/src/workspace.ts index 4e2846e684..0121c34632 100644 --- a/packages/core/src/workspace.ts +++ b/packages/core/src/workspace.ts @@ -23,7 +23,7 @@ export class Info extends Schema.Class("Workspace.Info")({ lastUsedAt: Schema.Number, }) {} -export class NotFound extends Schema.TaggedErrorClass()("Workspace.NotFound", { workspaceID: ID }) {} +export class NotFound extends Schema.TaggedError()("Workspace.NotFound", { workspaceID: ID }) {} export interface Interface { readonly create: (provider: string) => Effect.Effect diff --git a/packages/core/src/workspace/driver.ts b/packages/core/src/workspace/driver.ts index 4c08085906..6cfc51181f 100644 --- a/packages/core/src/workspace/driver.ts +++ b/packages/core/src/workspace/driver.ts @@ -14,12 +14,12 @@ import type { Driver as EnvironmentDriver } from "../environment/driver.js" export const Binding = Schema.Record(Schema.String, Schema.Json) export type Binding = typeof Binding.Type -export class Error extends Schema.TaggedErrorClass()("WorkspaceDriver.Error", { +export class Error extends Schema.TaggedError()("WorkspaceDriver.Error", { message: Schema.optional(Schema.String), cause: Schema.optional(Schema.Defect()), }) {} -export class ProviderNotFound extends Schema.TaggedErrorClass()("WorkspaceDriver.ProviderNotFound", { +export class ProviderNotFound extends Schema.TaggedError()("WorkspaceDriver.ProviderNotFound", { provider: Schema.String, }) {} diff --git a/packages/core/src/worktree.ts b/packages/core/src/worktree.ts index 01aaddf3b7..8eff88d506 100644 --- a/packages/core/src/worktree.ts +++ b/packages/core/src/worktree.ts @@ -56,27 +56,27 @@ export const ListEntry = Schema.Struct({ }).annotate({ identifier: "Worktree.ListEntry" }) export type ListEntry = typeof ListEntry.Type -export class SourceDirectoryNotFoundError extends Schema.TaggedErrorClass()( +export class SourceDirectoryNotFoundError extends Schema.TaggedError()( "Worktree.SourceDirectoryNotFoundError", { projectID: ProjectSchema.ID, directory: Schema.optional(AbsolutePath) }, ) {} -export class DestinationExistsError extends Schema.TaggedErrorClass()( +export class DestinationExistsError extends Schema.TaggedError()( "Worktree.DestinationExistsError", { directory: AbsolutePath }, ) {} -export class InvalidDirectoryError extends Schema.TaggedErrorClass()( +export class InvalidDirectoryError extends Schema.TaggedError()( "Worktree.InvalidDirectoryError", { directory: AbsolutePath }, ) {} -export class StrategyUnavailableError extends Schema.TaggedErrorClass()( +export class StrategyUnavailableError extends Schema.TaggedError()( "Worktree.StrategyUnavailableError", { strategy: StrategyID }, ) {} -export class DuplicateStrategyError extends Schema.TaggedErrorClass()( +export class DuplicateStrategyError extends Schema.TaggedError()( "Worktree.DuplicateStrategyError", { strategy: StrategyID }, ) {} diff --git a/packages/core/src/worktree/directory.ts b/packages/core/src/worktree/directory.ts index 4d240a1c65..9321027173 100644 --- a/packages/core/src/worktree/directory.ts +++ b/packages/core/src/worktree/directory.ts @@ -4,7 +4,7 @@ import { Effect, Schema } from "effect" import { FSUtil } from "@opencode-ai/util/fs-util" import { AbsolutePath } from "../schema.js" -export class DirectoryUnavailableError extends Schema.TaggedErrorClass()( +export class DirectoryUnavailableError extends Schema.TaggedError()( "Worktree.DirectoryUnavailableError", { directory: AbsolutePath }, ) {} diff --git a/packages/core/test/config/config.test.ts b/packages/core/test/config/config.test.ts index 3968c0ee40..d27fcf4fe8 100644 --- a/packages/core/test/config/config.test.ts +++ b/packages/core/test/config/config.test.ts @@ -541,10 +541,10 @@ describe("Config", () => { it.effect("migrates arbitrary v1 configuration into valid v2 configuration", () => Effect.sync(() => { FastCheck.assert( - FastCheck.property(Schema.toArbitrary(ConfigV1.Info), (info) => { + FastCheck.property(Schema.toArbitrary(ConfigV1.Info)(FastCheck), (info) => { const parsed = Schema.decodeUnknownSync(ConfigV1.Info)( - Schema.decodeUnknownSync(Schema.UnknownFromJsonString)( - Schema.encodeUnknownSync(Schema.UnknownFromJsonString)(info), + Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown))( + Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(info), ), ) Schema.decodeUnknownSync(Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" }) diff --git a/packages/core/test/config/normalization.test.ts b/packages/core/test/config/normalization.test.ts index 3d1401cd20..cf94ae86e3 100644 --- a/packages/core/test/config/normalization.test.ts +++ b/packages/core/test/config/normalization.test.ts @@ -81,7 +81,7 @@ describe("ConfigNormalize", () => { test("preserves arbitrary JSON-round-tripped native configuration", () => { FastCheck.assert( - FastCheck.property(Schema.toArbitrary(Info), (info) => { + FastCheck.property(Schema.toArbitrary(Info)(FastCheck), (info) => { const source = JSON.parse(JSON.stringify(Schema.encodeSync(Info)(info))) const result = normalized(source) expect(Schema.decodeUnknownSync(Info)(result.encoded)).toEqual( diff --git a/packages/core/test/session-runner-tool-registry.test.ts b/packages/core/test/session-runner-tool-registry.test.ts index a1be5eddab..e6ebfcd604 100644 --- a/packages/core/test/session-runner-tool-registry.test.ts +++ b/packages/core/test/session-runner-tool-registry.test.ts @@ -10,7 +10,7 @@ import { Tool } from "@opencode-ai/core/tool" import type { Info } from "@opencode-ai/schema/tool" import { LayerNode } from "@opencode-ai/util/effect/layer-node" import { executeTool, toolDefinitions } from "./lib/tool" -import { Cause, Deferred, Effect, Exit, Fiber, Layer, Option, Schema, SchemaGetter, SchemaIssue, Scope } from "effect" +import { Cause, Deferred, Effect, Exit, Fiber, Layer, Schema, SchemaGetter, SchemaIssue, Scope } from "effect" import { testEffect } from "./lib/effect" const imageStore = Layer.mock(Image.Service, { @@ -127,7 +127,7 @@ describe("Tool", () => { expect(error).toBeInstanceOf(Tool.RegistrationError) expect(error.name).toBe("phone_type") - expect(error.message).toContain('Expected string, got undefined\n at ["description"]') + expect(error.message).toContain('Expected string\n at ["description"]') expect((yield* service.snapshot()).definitions.map((tool) => tool.name)).toEqual(["execute"]) }), ) @@ -529,7 +529,7 @@ describe("Tool", () => { encode: SchemaGetter.transformOrFail((value) => value === "valid" ? Effect.succeed(true) - : Effect.fail(new SchemaIssue.InvalidValue(Option.some(value), { message: "invalid output" })), + : Effect.fail(new SchemaIssue.InvalidValue({ message: "invalid output" }, value)), ), }), ), diff --git a/packages/http-recorder/README.md b/packages/http-recorder/README.md index 10f828b8c4..f5f5bb1c4c 100644 --- a/packages/http-recorder/README.md +++ b/packages/http-recorder/README.md @@ -9,13 +9,13 @@ Use it for provider integrations, retries, polling, multi-step flows, and any te ## Install ```sh -bun add effect@4.0.0-beta.101 -bun add -d @opencode-ai/http-recorder @effect/vitest@4.0.0-beta.101 vitest@^4 +bun add effect@4.0.0-beta.107 +bun add -d @opencode-ai/http-recorder @effect/vitest@4.0.0-beta.107 vitest@^4 ``` The package supports Node.js 22+ and Bun. It is not intended for browsers, workers, or Deno. -Effect `4.0.0-beta.101` currently contains unresolved symbols in its published declarations. Until those upstream declarations are fixed, TypeScript consumers need: +Effect `4.0.0-beta.107` currently contains unresolved symbols in its published declarations. Until those upstream declarations are fixed, TypeScript consumers need: ```json { diff --git a/packages/http-recorder/package.json b/packages/http-recorder/package.json index 548e2e6da7..f73bf3e1e9 100644 --- a/packages/http-recorder/package.json +++ b/packages/http-recorder/package.json @@ -52,7 +52,7 @@ "typescript": "catalog:" }, "dependencies": { - "@effect/platform-node-shared": "4.0.0-beta.101" + "@effect/platform-node-shared": "4.0.0-beta.107" }, "peerDependencies": { "effect": "catalog:" diff --git a/packages/http-recorder/src/cassette/store.ts b/packages/http-recorder/src/cassette/store.ts index 2079632bea..e37f797d5a 100644 --- a/packages/http-recorder/src/cassette/store.ts +++ b/packages/http-recorder/src/cassette/store.ts @@ -6,7 +6,7 @@ import { CassetteSchema, encodeCassette, type Cassette, type CassetteMetadata, t const DEFAULT_RECORDINGS_DIR = path.resolve(process.cwd(), "test", "fixtures", "recordings") -export class CassetteNotFoundError extends Schema.TaggedErrorClass()("CassetteNotFoundError", { +export class CassetteNotFoundError extends Schema.TaggedError()("CassetteNotFoundError", { cassetteName: Schema.String, }) { override get message() { @@ -14,7 +14,7 @@ export class CassetteNotFoundError extends Schema.TaggedErrorClass()("InvalidCassetteError", { +export class InvalidCassetteError extends Schema.TaggedError()("InvalidCassetteError", { cassetteName: Schema.String, description: Schema.String, }) { @@ -23,7 +23,7 @@ export class InvalidCassetteError extends Schema.TaggedErrorClass()("UnsafeCassetteError", { +export class UnsafeCassetteError extends Schema.TaggedError()("UnsafeCassetteError", { cassetteName: Schema.String, findings: Schema.Array(SecretFindingSchema), }) { diff --git a/packages/http-recorder/src/redaction/redactor.ts b/packages/http-recorder/src/redaction/redactor.ts index d921f55d73..e21fc87082 100644 --- a/packages/http-recorder/src/redaction/redactor.ts +++ b/packages/http-recorder/src/redaction/redactor.ts @@ -28,7 +28,7 @@ const DEFAULT_REDACT_QUERY = [ "x-amz-security-token", "x-amz-signature", ] -const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const redactionSet = (values: ReadonlyArray | undefined, defaults: ReadonlyArray) => new Set([...defaults, ...(values ?? [])].map((value) => value.toLowerCase())) diff --git a/packages/http-recorder/src/replay/comparison.ts b/packages/http-recorder/src/replay/comparison.ts index 106dbd33a4..7d4827b75b 100644 --- a/packages/http-recorder/src/replay/comparison.ts +++ b/packages/http-recorder/src/replay/comparison.ts @@ -2,7 +2,7 @@ import { Option, Schema } from "effect" import { REDACTED } from "../redaction/redactor.js" import { secretFindings } from "../redaction/secrets.js" -export const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) +export const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)) const isRecord = (value: unknown): value is Record => value !== null && typeof value === "object" && !Array.isArray(value) diff --git a/packages/httpapi-codegen/src/index.ts b/packages/httpapi-codegen/src/index.ts index c01dc98a66..333d06e6a1 100644 --- a/packages/httpapi-codegen/src/index.ts +++ b/packages/httpapi-codegen/src/index.ts @@ -48,7 +48,7 @@ export type EffectOutputType = { type ResolvedEffectTypeReference = Omit & { readonly ast: SchemaAST.AST } -export class GenerationError extends Schema.TaggedErrorClass()("GenerationError", { +export class GenerationError extends Schema.TaggedError()("GenerationError", { reason: Schema.String, }) { override get message() { @@ -92,7 +92,6 @@ type PromiseInputField = const resolveHttpApiStatus = SchemaAST.resolveAt("httpApiStatus") const resolveHttpApiEncoding = SchemaAST.resolveAt("~httpApiEncoding") -const resolveContentSchema = SchemaAST.resolveAt("contentSchema") const Manifest = Schema.fromJsonString(Schema.Array(Schema.String)) const manifestName = ".httpapi-codegen.json" @@ -430,7 +429,7 @@ function effectTypeReferences(input: ReadonlyArray) { for (const reference of input) { const value = { name: reference.name, import: reference.import, ast: reference.schema.ast } const document = SchemaRepresentation.toCodeDocument( - SchemaRepresentation.fromASTs([Schema.toType(reference.schema).ast]), + SchemaRepresentation.toRepresentations([codegenAst(Schema.toType(reference.schema).ast)]), ) const name = document.codes[0]?.Type const type = @@ -462,7 +461,7 @@ function effectType(schema: Schema.Top, references: ReturnType [reference.$ref, reference.code.Type])) const expand = (type: string, seen = new Set()): string => { for (const [name, value] of source) { @@ -588,7 +587,7 @@ function renderEffectFiles(groups: ReadonlyArray): Output["files"] { { path: "client-error.ts", content: - 'import { Schema } from "effect"\n\nexport class ClientError extends Schema.TaggedErrorClass()("ClientError", {\n cause: Schema.Defect(),\n}) {}\n', + 'import { Schema } from "effect"\n\nexport class ClientError extends Schema.TaggedError()("ClientError", {\n cause: Schema.Defect(),\n}) {}\n', }, { path: "client.ts", content: renderClient(groups) }, { @@ -706,7 +705,7 @@ function renderImportedEffectFiles( { path: "client-error.ts", content: - 'import { Schema } from "effect"\n\nexport class ClientError extends Schema.TaggedErrorClass()("ClientError", {\n cause: Schema.Defect(),\n}) {}\n', + 'import { Schema } from "effect"\n\nexport class ClientError extends Schema.TaggedError()("ClientError", {\n cause: Schema.Defect(),\n}) {}\n', }, { path: "client.ts", content: client }, { @@ -983,9 +982,10 @@ function identifierPart(value: string) { function structuralTypes(schemas: ReadonlyArray, mutable: boolean, reservedNames: ReadonlySet) { if (schemas.length === 0) return { types: [], definitions: [] } - const document = SchemaRepresentation.toCodeDocument( - SchemaRepresentation.fromASTs(schemas.map((schema) => schema.ast) as [SchemaAST.AST, ...Array]), + const representations = SchemaRepresentation.toRepresentations( + promiseTypeAsts(schemas) as [SchemaAST.AST, ...Array], ) + const document = SchemaRepresentation.toCodeDocument(representations) if ( document.artifacts.some( (artifact) => @@ -995,9 +995,35 @@ function structuralTypes(schemas: ReadonlyArray, mutable: boolean, r ) { throw new GenerationError({ reason: "Referenced Promise types are not implemented" }) } + const anonymous = new Set( + Object.entries(representations.references) + .filter(([, reference]) => { + if (!("annotations" in reference) || reference.annotations === undefined) return true + return reference.annotations.identifier === undefined && reference.annotations["~identifier"] === undefined + }) + .map(([name]) => name), + ) + const anonymousTypes = new Map( + document.references.nonRecursives + .filter((reference) => anonymous.has(reference.$ref)) + .map((reference) => [reference.$ref, reference.code.Type]), + ) + const inlineAnonymous = (type: string, seen = new Set()): string => { + for (const [reference, value] of anonymousTypes) { + const pattern = `(?() const usedNames = new Set(reservedNames) - for (const reference of document.references.nonRecursives) { + const references = document.references.nonRecursives.filter((reference) => !anonymous.has(reference.$ref)) + const referenceNames = new Set(references.map((reference) => reference.$ref)) + for (const reference of references) { const seed = identifierPart(reference.$ref) const name = uniqueTypeName(seed, usedNames) names.set(reference.$ref, name) @@ -1014,11 +1040,30 @@ function structuralTypes(schemas: ReadonlyArray, mutable: boolean, r .replaceAll(/(?() + for (const reference of references) { + const base = reference.$ref.replace(/_\d+$/, "") + const identifier = referenceNames.has(base) ? base : reference.$ref + const key = `${identifier}\0${render(inlineAnonymous(reference.code.Type))}` + const existing = equivalent.get(key) + if (existing !== undefined) { + names.set(reference.$ref, existing) + continue + } + const name = names.get(reference.$ref) + if (name === undefined) throw new GenerationError({ reason: `Missing Promise type name: ${reference.$ref}` }) + equivalent.set(key, name) + } + const emitted = new Set() return { - types: document.codes.map((code) => render(code.Type)), - definitions: document.references.nonRecursives.map( - (reference) => `export type ${names.get(reference.$ref)} = ${render(reference.code.Type)}`, - ), + types: document.codes.map((code) => render(inlineAnonymous(code.Type))), + definitions: references.flatMap((reference) => { + const name = names.get(reference.$ref) + if (name === undefined) throw new GenerationError({ reason: `Missing Promise type name: ${reference.$ref}` }) + if (emitted.has(name)) return [] + emitted.add(name) + return [`export type ${name} = ${render(inlineAnonymous(reference.code.Type))}`] + }), } } @@ -1028,7 +1073,7 @@ function uniqueTypeName(seed: string, used: ReadonlySet, suffix = 1): st } function structuralType(schema: Schema.Top) { - const document = SchemaRepresentation.toCodeDocument(SchemaRepresentation.fromASTs([schema.ast])) + const document = SchemaRepresentation.toCodeDocument(SchemaRepresentation.toRepresentations([promiseTypeAst(schema)])) if ( document.artifacts.some( (artifact) => @@ -1059,6 +1104,63 @@ function structuralType(schema: Schema.Top) { ) } +function promiseTypeAst(schema: Schema.Top) { + return codegenAst(schema.ast) +} + +function promiseTypeAsts(schemas: ReadonlyArray) { + return codegenAsts(schemas.map((schema) => schema.ast)) +} + +function codegenAst(root: SchemaAST.AST) { + return codegenAsts([root])[0] +} + +function codegenAsts(roots: ReadonlyArray) { + const cache = new WeakMap() + const references = new Map() + const recur = (ast: SchemaAST.AST): SchemaAST.AST => { + const cached = cache.get(ast) + if (cached !== undefined) return cached + const identifier = SchemaAST.resolveIdentifier(ast) + const output = normalize(ast) + const referenceKey = + identifier === undefined + ? undefined + : `${identifier}\0${ast.context?.isOptional === true}\0${ast.context?.isMutable === true}\0${representationEncoding(output)}` + const reference = referenceKey === undefined ? undefined : references.get(referenceKey) + if (reference !== undefined) { + cache.set(ast, reference) + return reference + } + cache.set(ast, output) + if (referenceKey !== undefined) references.set(referenceKey, output) + return output + } + const normalize = (ast: SchemaAST.AST): SchemaAST.AST => { + if (SchemaAST.isDeclaration(ast) && ast.annotations?.toCode === undefined) { + const representation = ast.annotations?.representation + if ( + typeof representation === "object" && + representation !== null && + "id" in representation && + representation.id === "effect/schema/Json" + ) { + return Schema.Json.ast + } + if (ast.annotations?.["~constructor"] !== undefined && ast.typeParameters[0] !== undefined) { + const identifier = SchemaAST.resolveIdentifier(ast) + const fields = recur(ast.typeParameters[0]) + if (identifier === undefined) return fields + return Schema.make(fields).annotate({ identifier }).ast + } + } + if (!("recur" in ast) || typeof ast.recur !== "function") return ast + return ast.recur(recur) + } + return roots.map(recur) +} + function preserveStringSuggestions(type: string) { return type.replaceAll(/((?:"(?:\\.|[^"\\])*"\s*\|\s*)+)string\b/g, "$1(string & {})") } @@ -1206,40 +1308,64 @@ function isPathInput(path: string): path is HttpRouter.PathInput { return path === "*" || path.startsWith("/") } +const encodings = new WeakMap() + function sameEncoding(left: SchemaAST.AST, right: SchemaAST.AST): boolean { + if (!sameRuntimeEncoding(left, right)) return false + return sameRepresentation(left, right) +} + +function sameRepresentation(left: SchemaAST.AST, right: SchemaAST.AST): boolean { + return representationEncoding(left) === representationEncoding(right) +} + +function representationEncoding(ast: SchemaAST.AST) { + const cached = encodings.get(ast) + if (cached !== undefined) return cached + const encoded = JSON.stringify(SchemaRepresentation.toJson(SchemaRepresentation.toRepresentation(ast))) + encodings.set(ast, encoded) + return encoded +} + +function sameRuntimeEncoding(left: SchemaAST.AST, right: SchemaAST.AST): boolean { if (left._tag !== right._tag || left.encoding?.length !== right.encoding?.length) return false if ( left.encoding?.some((link, index) => { const other = right.encoding?.[index] - return other === undefined || link.transformation !== other.transformation || !sameEncoding(link.to, other.to) + return other === undefined || !sameRuntimeEncoding(link.to, other.to) }) - ) + ) { return false + } if (!sameChecks(left.checks, right.checks) || !sameContext(left.context, right.context)) return false - if (SchemaAST.isSuspend(left) && SchemaAST.isSuspend(right)) return sameEncoding(left.thunk(), right.thunk()) + if (SchemaAST.isSuspend(left) && SchemaAST.isSuspend(right)) { + return sameRuntimeEncoding(left.thunk(), right.thunk()) + } if (SchemaAST.isUnion(left) && SchemaAST.isUnion(right)) { return ( left.types.length === right.types.length && - left.types.every((ast, index) => sameEncoding(ast, right.types[index])) + left.types.every((ast, index) => sameRuntimeEncoding(ast, right.types[index])) ) } if (SchemaAST.isArrays(left) && SchemaAST.isArrays(right)) { return ( left.elements.length === right.elements.length && left.rest.length === right.rest.length && - left.elements.every((ast, index) => sameEncoding(ast, right.elements[index])) && - left.rest.every((ast, index) => sameEncoding(ast, right.rest[index])) + left.elements.every((ast, index) => sameRuntimeEncoding(ast, right.elements[index])) && + left.rest.every((ast, index) => sameRuntimeEncoding(ast, right.rest[index])) ) } if (SchemaAST.isObjects(left) && SchemaAST.isObjects(right)) { return ( left.propertySignatures.length === right.propertySignatures.length && left.indexSignatures.length === right.indexSignatures.length && - left.propertySignatures.every((field, index) => sameEncoding(field.type, right.propertySignatures[index].type)) && + left.propertySignatures.every((field, index) => + sameRuntimeEncoding(field.type, right.propertySignatures[index].type), + ) && left.indexSignatures.every( (field, index) => - sameEncoding(field.parameter, right.indexSignatures[index].parameter) && - sameEncoding(field.type, right.indexSignatures[index].type), + sameRuntimeEncoding(field.parameter, right.indexSignatures[index].parameter) && + sameRuntimeEncoding(field.type, right.indexSignatures[index].type), ) ) } @@ -1399,9 +1525,9 @@ function assertPortable(schema: Schema.Top, path: string, portable: Map check._tag === "Filter" ? !check.aborted && - check.annotations?.meta !== undefined && + check.annotations?.representation !== undefined && + serializable(check.annotations.representation) && typeof check.annotations.arbitrary === "object" && check.annotations.arbitrary !== null && "constraint" in check.annotations.arbitrary @@ -1469,38 +1596,23 @@ function metadataPortable(ast: SchemaAST.AST, seen: Set): boolean return true } -function generationPortable(generation: unknown): boolean { - if (typeof generation !== "object" || generation === null) return false - const value = generation as { - readonly runtime?: unknown - readonly Type?: unknown - readonly importDeclaration?: unknown - } - if (typeof value.runtime !== "string" || typeof value.Type !== "string") return false - if (value.importDeclaration !== undefined) { - if ( - typeof value.importDeclaration !== "string" || - !/from ["']effect(?:\/[^"']+)?["']$/.test(value.importDeclaration) - ) { - return false - } - } - const namespace = - typeof value.importDeclaration === "string" - ? /import(?: type)? \* as ([A-Za-z_$][\w$]*)/.exec(value.importDeclaration)?.[1] - : undefined - return value.runtime.startsWith("Schema.") || (namespace !== undefined && value.runtime.startsWith(`${namespace}.`)) -} - function annotationsPortable(annotations: Schema.Annotations.Annotations | undefined) { if (annotations === undefined) return true return Object.entries(annotations).every(([key, value]) => { if ( - ["toCodec", "toCodecJson", "toArbitrary", "toFormatter", "toEquivalence", "~effect/Schema/Class"].includes(key) + [ + "toCodec", + "toCodecJson", + "toCodecStringTree", + "toArbitrary", + "toFormatter", + "toEquivalence", + "toCode", + "~constructor", + ].includes(key) ) { return true } - if (key === "generation") return generationPortable(value) return serializable(value) }) } @@ -1518,7 +1630,7 @@ function taggedErrorFields(schema: Schema.Top) { } function declaredErrorFields(schema: Schema.Top) { - if (!SchemaAST.isDeclaration(schema.ast) || schema.ast.annotations?.["~effect/Schema/Class"] === undefined) { + if (!SchemaAST.isDeclaration(schema.ast) || schema.ast.annotations?.["~constructor"] === undefined) { return undefined } const fields = schema.ast.typeParameters[0] @@ -1559,12 +1671,11 @@ function streamDataSchema(schema: Extract) { - const data = streamDataAst(schema.events.ast) - const encodedAst = data.encoding?.at(-1)?.to - if (encodedAst === undefined) throw new GenerationError({ reason: "Invalid SSE data schema" }) - const encoded = resolveContentSchema(encodedAst) - if (!SchemaAST.isAST(encoded)) throw new GenerationError({ reason: "Invalid SSE data schema" }) - return Schema.make(encoded) + const replaceEncoding: unknown = Reflect.get(SchemaAST, "replaceEncoding") + if (typeof replaceEncoding !== "function") throw new GenerationError({ reason: "Invalid SSE data schema" }) + const ast: unknown = replaceEncoding(streamDataAst(schema.events.ast), undefined) + if (!SchemaAST.isAST(ast)) throw new GenerationError({ reason: "Invalid SSE data schema" }) + return Schema.toEncoded(Schema.make(ast)) } function streamDataAst(ast: SchemaAST.AST) { @@ -1733,12 +1844,15 @@ function renderSchemas(slots: ReadonlyArray) { ] const [first, ...rest] = expanded const document = SchemaRepresentation.toCodeDocument( - SchemaRepresentation.fromASTs([first.schema.ast, ...rest.map((slot) => slot.schema.ast)]), + SchemaRepresentation.toRepresentations(codegenAsts(expanded.map((slot) => slot.schema.ast)) as [ + SchemaAST.AST, + ...Array, + ]), ) const artifacts = document.artifacts.flatMap((artifact) => { if (artifact._tag === "Import") return [artifact.importDeclaration] - if (artifact._tag === "Enum") return [artifact.generation.runtime] - return [`const ${artifact.identifier} = ${artifact.generation.runtime}`] + if (artifact._tag === "Enum") return [artifact.code.runtime] + return [`const ${artifact.identifier} = ${artifact.code.runtime}`] }) const references = [ ...document.references.nonRecursives.map(({ $ref, code }) => `const ${$ref} = ${code.runtime}`), @@ -1761,7 +1875,7 @@ function renderSchemas(slots: ReadonlyArray) { annotations.length === 0 ? "" : `.annotate({ ${annotations.map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`).join(", ")} })` - return `class ${slot.name}Class extends Schema.TaggedErrorClass<${slot.name}Class>(${JSON.stringify(tagged.identifier)})(${JSON.stringify(tagged.tag)}, { ${fields} }) {}\nconst ${slot.name} = ${slot.name}Class${annotate}` + return `class ${slot.name}Class extends Schema.TaggedError<${slot.name}Class>(${JSON.stringify(tagged.identifier)})(${JSON.stringify(tagged.tag)}, { ${fields} }) {}\nconst ${slot.name} = ${slot.name}Class${annotate}` }) return [...artifacts, ...references, ...declarations].join("\n\n") } diff --git a/packages/httpapi-codegen/test/fixture.ts b/packages/httpapi-codegen/test/fixture.ts index 3dc3cc694d..6210cd1422 100644 --- a/packages/httpapi-codegen/test/fixture.ts +++ b/packages/httpapi-codegen/test/fixture.ts @@ -1,7 +1,7 @@ import { Schema } from "effect" import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi" -export class Missing extends Schema.TaggedErrorClass()("Missing", { +export class Missing extends Schema.TaggedError()("Missing", { message: Schema.String, }) {} diff --git a/packages/httpapi-codegen/test/generate.test.ts b/packages/httpapi-codegen/test/generate.test.ts index 32a400d471..bde4f21a37 100644 --- a/packages/httpapi-codegen/test/generate.test.ts +++ b/packages/httpapi-codegen/test/generate.test.ts @@ -504,7 +504,7 @@ describe("HttpApiCodegen.generate", () => { }) test("preserves optional keys in Promise error types", () => { - class OptionalError extends Schema.TaggedErrorClass()( + class OptionalError extends Schema.TaggedError()( "OptionalError", { message: Schema.String, detail: Schema.String.pipe(Schema.optional) }, { httpApiStatus: 400 }, @@ -519,7 +519,7 @@ describe("HttpApiCodegen.generate", () => { }) test("supports name-discriminated Promise errors", () => { - class NamedError extends Schema.ErrorClass("NamedError")( + class NamedError extends Schema.Error("NamedError")( { name: Schema.Literal("NamedError"), message: Schema.String }, { httpApiStatus: 400 }, ) {} @@ -535,7 +535,7 @@ describe("HttpApiCodegen.generate", () => { }) test("preserves reflected default error statuses", () => { - class MissingStatus extends Schema.TaggedErrorClass()("MissingStatus", { + class MissingStatus extends Schema.TaggedError()("MissingStatus", { message: Schema.String, }) {} const output = emitPromise( @@ -579,10 +579,14 @@ describe("HttpApiCodegen.generate", () => { const Referenced = Schema.Struct({ value: Schema.String }).annotate({ identifier: "Referenced" }) const output = emitPromise( compileContract( - api( - HttpApiEndpoint.get("get", "/session", { - success: Schema.Struct({ data: Referenced }), - }), + HttpApi.make("test").add( + HttpApiGroup.make("session") + .add(HttpApiEndpoint.get("get", "/session", { success: Schema.Struct({ data: Referenced }) })) + .add( + HttpApiEndpoint.get("list", "/sessions", { + success: Schema.Struct({ data: Schema.Array(Referenced) }), + }), + ), ), ), ) @@ -590,6 +594,21 @@ describe("HttpApiCodegen.generate", () => { const types = output.files.find((file) => file.path === "types.ts")?.content expect(types).toContain('export type Referenced = { readonly "value": string }') expect(types).toContain('export type SessionGetOutput = ({ readonly "data": Referenced })["data"]') + expect(types).not.toContain("Referenced1") + }) + + test("inlines shared anonymous Promise wire types", () => { + const Shared = Schema.Struct({ value: Schema.String }) + const output = emitPromise( + compileContract( + api(HttpApiEndpoint.get("get", "/session", { success: Schema.Struct({ first: Shared, second: Shared }) })), + ), + ) + const types = output.files.find((file) => file.path === "types.ts")?.content + + expect(types).toContain('readonly "first": ({ readonly "value": string })') + expect(types).toContain('readonly "second": ({ readonly "value": string })') + expect(types).not.toContain("export type Objects") }) test("emits mutable Promise outputs without restricting inputs", () => { @@ -647,6 +666,37 @@ describe("HttpApiCodegen.generate", () => { expect(types).toContain("export type ExampleName2 = string") }) + test("keeps conflicting Promise reference identifiers distinct", () => { + const First = Schema.Struct({ value: Schema.String }).annotate({ identifier: "Shared" }) + const Second = Schema.Struct({ value: Schema.Number }).annotate({ identifier: "Shared" }) + + const output = emitPromise( + compileContract( + api(HttpApiEndpoint.get("get", "/session", { success: Schema.Struct({ first: First, second: Second }) })), + ), + ) + const types = output.files.find((file) => file.path === "types.ts")?.content + + expect(types).toContain('export type Shared = { readonly "value": string }') + expect(types).toContain('export type Shared1 = { readonly "value": number }') + expect(types).toContain('readonly "first": Shared, readonly "second": Shared1') + }) + + test("deduplicates equivalent Promise references with the same identifier", () => { + const First = Schema.String.annotate({ identifier: "Shared", description: "first" }) + const Second = Schema.String.annotate({ identifier: "Shared", description: "second" }) + const output = emitPromise( + compileContract( + api(HttpApiEndpoint.get("get", "/session", { success: Schema.Struct({ first: First, second: Second }) })), + ), + ) + const types = output.files.find((file) => file.path === "types.ts")?.content + + expect(types).toContain("export type Shared = string") + expect(types).not.toContain("export type Shared1") + expect(types).toContain('readonly "first": Shared, readonly "second": Shared') + }) + test("emits Effect Json schemas as standalone Promise types", () => { const output = emitPromise( compileContract( @@ -1347,6 +1397,19 @@ describe("HttpApiCodegen.generate", () => { ).toThrow("Effect schema requires authoritative import: session.get") }) + test("rejects same-shape custom transformations", () => { + const Trimmed = Schema.String.pipe( + Schema.decodeTo(Schema.String, { + decode: SchemaGetter.transform((value) => value.trim()), + encode: SchemaGetter.transform((value) => value), + }), + ) + + expect(() => compile(api(HttpApiEndpoint.get("get", "/session", { success: Trimmed })))).toThrow( + "Effect schema requires authoritative import: session.get", + ) + }) + test("rejects custom validation checks without portable metadata", () => { const Positive = Schema.Number.check(Schema.makeFilter((value) => (value > 0 ? undefined : "positive"))) @@ -1404,7 +1467,7 @@ describe("HttpApiCodegen.generate", () => { }) test("preserves errors from server-only middleware", () => { - class Unauthorized extends Schema.TaggedErrorClass()("Unauthorized", {}) {} + class Unauthorized extends Schema.TaggedError()("Unauthorized", {}) {} class Authorization extends HttpApiMiddleware.Service()("Authorization", { error: Unauthorized, }) {} @@ -1415,12 +1478,12 @@ describe("HttpApiCodegen.generate", () => { expect(output.operations[0]).toBeDefined() expect(output.files.find((file) => file.path === "session.ts")?.content).toContain( - 'extends Schema.TaggedErrorClass("Unauthorized")', + 'extends Schema.TaggedError("Unauthorized")', ) }) test("preserves tagged error response statuses", () => { - class Missing extends Schema.TaggedErrorClass()("Missing", {}) {} + class Missing extends Schema.TaggedError()("Missing", {}) {} const output = compile( api( HttpApiEndpoint.get("get", "/session", { diff --git a/packages/httpapi-codegen/test/generated/client-error.ts b/packages/httpapi-codegen/test/generated/client-error.ts index bcc65d9bdd..858cb704f5 100644 --- a/packages/httpapi-codegen/test/generated/client-error.ts +++ b/packages/httpapi-codegen/test/generated/client-error.ts @@ -1,5 +1,5 @@ import { Schema } from "effect" -export class ClientError extends Schema.TaggedErrorClass()("ClientError", { +export class ClientError extends Schema.TaggedError()("ClientError", { cause: Schema.Defect(), }) {} diff --git a/packages/httpapi-codegen/test/generated/session.ts b/packages/httpapi-codegen/test/generated/session.ts index dc288a175f..ced2f16db2 100644 --- a/packages/httpapi-codegen/test/generated/session.ts +++ b/packages/httpapi-codegen/test/generated/session.ts @@ -15,7 +15,7 @@ const Endpoint2Params = Schema.Struct({ sessionID: Schema.String }) const Endpoint2Success = Schema.Struct({ data: Schema.String }) -class Endpoint2Error0Class extends Schema.TaggedErrorClass("Missing")("Missing", { +class Endpoint2Error0Class extends Schema.TaggedError("Missing")("Missing", { message: Schema.String, }) {} const Endpoint2Error0 = Endpoint2Error0Class.annotate({ httpApiStatus: 404 }) diff --git a/packages/protocol/src/errors.ts b/packages/protocol/src/errors.ts index fea0b498b6..f3240fa5c5 100644 --- a/packages/protocol/src/errors.ts +++ b/packages/protocol/src/errors.ts @@ -1,7 +1,7 @@ import { Schema } from "effect" import { Skill } from "@opencode-ai/schema/skill" -export class InvalidRequestError extends Schema.TaggedErrorClass()( +export class InvalidRequestError extends Schema.TaggedError()( "InvalidRequestError", { message: Schema.String, @@ -11,13 +11,13 @@ export class InvalidRequestError extends Schema.TaggedErrorClass()( +export class UnauthorizedError extends Schema.TaggedError()( "UnauthorizedError", { message: Schema.String }, { httpApiStatus: 401 }, ) {} -export class ConflictError extends Schema.TaggedErrorClass()( +export class ConflictError extends Schema.TaggedError()( "ConflictError", { message: Schema.String, @@ -26,7 +26,7 @@ export class ConflictError extends Schema.TaggedErrorClass()( { httpApiStatus: 409 }, ) {} -export class SessionBusyError extends Schema.TaggedErrorClass()( +export class SessionBusyError extends Schema.TaggedError()( "SessionBusyError", { sessionID: Schema.String, @@ -35,7 +35,7 @@ export class SessionBusyError extends Schema.TaggedErrorClass( { httpApiStatus: 409 }, ) {} -export class ServiceUnavailableError extends Schema.TaggedErrorClass()( +export class ServiceUnavailableError extends Schema.TaggedError()( "ServiceUnavailableError", { message: Schema.String, @@ -44,7 +44,7 @@ export class ServiceUnavailableError extends Schema.TaggedErrorClass()( +export class UnknownError extends Schema.TaggedError()( "UnknownError", { message: Schema.String, @@ -53,7 +53,7 @@ export class UnknownError extends Schema.TaggedErrorClass()( { httpApiStatus: 500 }, ) {} -export class ProviderNotFoundError extends Schema.TaggedErrorClass()( +export class ProviderNotFoundError extends Schema.TaggedError()( "ProviderNotFoundError", { providerID: Schema.String, @@ -62,7 +62,7 @@ export class ProviderNotFoundError extends Schema.TaggedErrorClass()( +export class AgentNotFoundError extends Schema.TaggedError()( "AgentNotFoundError", { agentID: Schema.String, @@ -71,7 +71,7 @@ export class AgentNotFoundError extends Schema.TaggedErrorClass()( +export class SessionNotFoundError extends Schema.TaggedError()( "SessionNotFoundError", { sessionID: Schema.String, @@ -80,7 +80,7 @@ export class SessionNotFoundError extends Schema.TaggedErrorClass()( +export class MessageNotFoundError extends Schema.TaggedError()( "MessageNotFoundError", { sessionID: Schema.String, @@ -90,7 +90,7 @@ export class MessageNotFoundError extends Schema.TaggedErrorClass()( +export class SkillNotFoundError extends Schema.TaggedError()( "SkillNotFoundError", { skill: Skill.ID, @@ -99,7 +99,7 @@ export class SkillNotFoundError extends Schema.TaggedErrorClass()( +export class McpServerNotFoundError extends Schema.TaggedError()( "McpServerNotFoundError", { server: Schema.String, @@ -108,7 +108,7 @@ export class McpServerNotFoundError extends Schema.TaggedErrorClass()( +export class CommandNotFoundError extends Schema.TaggedError()( "CommandNotFoundError", { command: Schema.String, @@ -117,7 +117,7 @@ export class CommandNotFoundError extends Schema.TaggedErrorClass()( +export class CommandEvaluationError extends Schema.TaggedError()( "CommandEvaluationError", { command: Schema.String, @@ -126,13 +126,13 @@ export class CommandEvaluationError extends Schema.TaggedErrorClass()( +export class InvalidCursorError extends Schema.TaggedError()( "InvalidCursorError", { message: Schema.String }, { httpApiStatus: 400 }, ) {} -export class PermissionNotFoundError extends Schema.TaggedErrorClass()( +export class PermissionNotFoundError extends Schema.TaggedError()( "PermissionNotFoundError", { requestID: Schema.String, @@ -141,7 +141,7 @@ export class PermissionNotFoundError extends Schema.TaggedErrorClass()( +export class FormNotFoundError extends Schema.TaggedError()( "FormNotFoundError", { id: Schema.String, @@ -150,7 +150,7 @@ export class FormNotFoundError extends Schema.TaggedErrorClass()( +export class FormAlreadySettledError extends Schema.TaggedError()( "FormAlreadySettledError", { id: Schema.String, @@ -159,7 +159,7 @@ export class FormAlreadySettledError extends Schema.TaggedErrorClass()( +export class FormInvalidAnswerError extends Schema.TaggedError()( "FormInvalidAnswerError", { id: Schema.String, @@ -168,13 +168,13 @@ export class FormInvalidAnswerError extends Schema.TaggedErrorClass()( +export class ForbiddenError extends Schema.TaggedError()( "ForbiddenError", { message: Schema.String }, { httpApiStatus: 403 }, ) {} -export class PtyNotFoundError extends Schema.TaggedErrorClass()( +export class PtyNotFoundError extends Schema.TaggedError()( "PtyNotFoundError", { ptyID: Schema.String, @@ -183,7 +183,7 @@ export class PtyNotFoundError extends Schema.TaggedErrorClass( { httpApiStatus: 404 }, ) {} -export class ShellNotFoundError extends Schema.TaggedErrorClass()( +export class ShellNotFoundError extends Schema.TaggedError()( "ShellNotFoundError", { id: Schema.String, diff --git a/packages/protocol/src/groups/worktree.ts b/packages/protocol/src/groups/worktree.ts index 14a5fb340d..3fd4788f70 100644 --- a/packages/protocol/src/groups/worktree.ts +++ b/packages/protocol/src/groups/worktree.ts @@ -5,7 +5,7 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/un const root = "/api/worktree/:projectID" -export class WorktreeError extends Schema.ErrorClass("WorktreeError")( +export class WorktreeError extends Schema.Error("WorktreeError")( { name: Schema.Literal("WorktreeError"), data: Schema.Struct({ diff --git a/packages/protocol/src/simulation.ts b/packages/protocol/src/simulation.ts index 43b50fc8b6..f9700d5a35 100644 --- a/packages/protocol/src/simulation.ts +++ b/packages/protocol/src/simulation.ts @@ -60,7 +60,7 @@ export namespace JsonRpc { } } -export class SimulationRequestError extends Schema.TaggedErrorClass()( +export class SimulationRequestError extends Schema.TaggedError()( "SimulationRequestError", { method: Schema.String, @@ -131,7 +131,7 @@ export namespace Handshake { readonly capabilities: ReadonlyArray } - export class RoleMismatchError extends Schema.TaggedErrorClass()( + export class RoleMismatchError extends Schema.TaggedError()( "SimulationHandshake.RoleMismatchError", { expected: EndpointRole, @@ -140,7 +140,7 @@ export namespace Handshake { }, ) {} - export class UnsupportedProtocolError extends Schema.TaggedErrorClass()( + export class UnsupportedProtocolError extends Schema.TaggedError()( "SimulationHandshake.UnsupportedProtocolError", { offered: Schema.Array(Schema.Number), @@ -149,7 +149,7 @@ export namespace Handshake { }, ) {} - export class MissingCapabilityError extends Schema.TaggedErrorClass()( + export class MissingCapabilityError extends Schema.TaggedError()( "SimulationHandshake.MissingCapabilityError", { missing: Schema.Array(Capability), diff --git a/packages/schema/src/instruction-entry.ts b/packages/schema/src/instruction-entry.ts index 6e25e9cbaf..4d1bfdbe7a 100644 --- a/packages/schema/src/instruction-entry.ts +++ b/packages/schema/src/instruction-entry.ts @@ -21,7 +21,7 @@ export interface Info extends Schema.Schema.Type {} export const MaxValueBytes = 8 * 1024 -export class ValueTooLargeError extends Schema.TaggedErrorClass()( +export class ValueTooLargeError extends Schema.TaggedError()( "InstructionEntryValueTooLargeError", { actualBytes: Schema.Int, diff --git a/packages/schema/src/tool.ts b/packages/schema/src/tool.ts index f2e82a4f30..c325026526 100644 --- a/packages/schema/src/tool.ts +++ b/packages/schema/src/tool.ts @@ -56,7 +56,7 @@ type OutputValue = S extends undefined ? A : any -export class Error extends Schema.TaggedErrorClass()("Tool.Error", { +export class Error extends Schema.TaggedError()("Tool.Error", { message: Schema.String, error: Schema.optional(Schema.Defect()), metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)), diff --git a/packages/server/src/event-feed.ts b/packages/server/src/event-feed.ts index 3ada137c5d..870ae221f4 100644 --- a/packages/server/src/event-feed.ts +++ b/packages/server/src/event-feed.ts @@ -7,12 +7,12 @@ import { Cause, Context, Effect, Layer, Queue, Schema, Scope, Stream } from "eff export const SubscriberCapacity = 4_096 -export class SubscriberOverflowError extends Schema.TaggedErrorClass()( +export class SubscriberOverflowError extends Schema.TaggedError()( "EventFeed.SubscriberOverflow", { capacity: Schema.Int }, ) {} -export class EncodingError extends Schema.TaggedErrorClass()("EventFeed.EncodingError", { +export class EncodingError extends Schema.TaggedError()("EventFeed.EncodingError", { eventID: Event.ID, eventType: Schema.String, cause: Schema.Defect(), diff --git a/packages/simulation/src/backend/simulated-provider.ts b/packages/simulation/src/backend/simulated-provider.ts index ffc637d169..1d5a255419 100644 --- a/packages/simulation/src/backend/simulated-provider.ts +++ b/packages/simulation/src/backend/simulated-provider.ts @@ -32,7 +32,7 @@ export type ProviderResponseEvent = | SimulationProtocol.Backend.Item | { readonly type: "finish"; readonly reason: SimulationProtocol.Backend.FinishReason } -export class ProviderDisconnectedError extends Schema.TaggedErrorClass()( +export class ProviderDisconnectedError extends Schema.TaggedError()( "SimulatedProvider.ProviderDisconnectedError", { message: Schema.String }, ) {} @@ -132,22 +132,22 @@ interface ToolDriver { readonly shutdown: Effect.Effect } -class InvocationNotFoundError extends Schema.TaggedErrorClass()( +class InvocationNotFoundError extends Schema.TaggedError()( "SimulatedProvider.InvocationNotFoundError", { id: Schema.String, message: Schema.String }, ) {} -class ControllerDisconnectedError extends Schema.TaggedErrorClass()( +class ControllerDisconnectedError extends Schema.TaggedError()( "SimulatedProvider.ControllerDisconnectedError", { message: Schema.String }, ) {} -class ToolInvocationNotFoundError extends Schema.TaggedErrorClass()( +class ToolInvocationNotFoundError extends Schema.TaggedError()( "SimulatedProvider.ToolInvocationNotFoundError", { id: Schema.String, message: Schema.String }, ) {} -class ToolControllerError extends Schema.TaggedErrorClass()( +class ToolControllerError extends Schema.TaggedError()( "SimulatedProvider.ToolControllerError", { message: Schema.String }, ) {} diff --git a/packages/simulation/src/manifest.ts b/packages/simulation/src/manifest.ts index fe276ee688..271f12823a 100644 --- a/packages/simulation/src/manifest.ts +++ b/packages/simulation/src/manifest.ts @@ -43,7 +43,7 @@ export const Manifest = Schema.Struct({ }) export interface Manifest extends Schema.Schema.Type {} -export class ResolveError extends Schema.TaggedErrorClass()("DriveManifest.ResolveError", { +export class ResolveError extends Schema.TaggedError()("DriveManifest.ResolveError", { reason: Schema.Literals(["config", "not-found", "read", "decode"]), path: Schema.optionalKey(Schema.String), message: Schema.String, diff --git a/packages/theme/src/tui/resolve.ts b/packages/theme/src/tui/resolve.ts index aa582832e9..835dc3dcbc 100644 --- a/packages/theme/src/tui/resolve.ts +++ b/packages/theme/src/tui/resolve.ts @@ -26,7 +26,7 @@ import type { } from "./index.js" import { selectTheme, selectThemeMode } from "./select.js" -const decodeThemeDefinitionSchema = Schema.decodeUnknownSync(ThemeDefinition) +const decodeThemeDefinitionSchema = Schema.decodeUnknownSync(ThemeDefinition, { reportInput: true }) function decodeThemeDefinition(input: unknown) { try { diff --git a/packages/tui/src/theme/index.ts b/packages/tui/src/theme/index.ts index 320b894137..205649a28b 100644 --- a/packages/tui/src/theme/index.ts +++ b/packages/tui/src/theme/index.ts @@ -13,7 +13,7 @@ let customThemes: Record = {} let systemTheme: ThemeDocumentSource | undefined const listeners = new Set<(themes: Record) => void>() const parsed = new WeakMap() -const decodeThemeDocument = Schema.decodeUnknownSync(ThemeDocument) +const decodeThemeDocument = Schema.decodeUnknownSync(ThemeDocument, { reportInput: true }) function listThemes() { // Priority: defaults < plugin installs < custom files < generated system. diff --git a/packages/util/src/effect-flock.ts b/packages/util/src/effect-flock.ts index 5fa3779951..788fd81d0d 100644 --- a/packages/util/src/effect-flock.ts +++ b/packages/util/src/effect-flock.ts @@ -14,15 +14,15 @@ export namespace EffectFlock { // Errors // --------------------------------------------------------------------------- - export class LockTimeoutError extends Schema.TaggedErrorClass()("LockTimeoutError", { + export class LockTimeoutError extends Schema.TaggedError()("LockTimeoutError", { key: Schema.String, }) {} - export class LockCompromisedError extends Schema.TaggedErrorClass()("LockCompromisedError", { + export class LockCompromisedError extends Schema.TaggedError()("LockCompromisedError", { detail: Schema.String, }) {} - class ReleaseError extends Schema.TaggedErrorClass()("ReleaseError", { + class ReleaseError extends Schema.TaggedError()("ReleaseError", { detail: Schema.String, cause: Schema.optional(Schema.Defect()), }) { @@ -32,7 +32,7 @@ export namespace EffectFlock { } /** Internal: signals "lock is held, retry later". Never leaks to callers. */ - class NotAcquired extends Schema.TaggedErrorClass()("NotAcquired", {}) {} + class NotAcquired extends Schema.TaggedError()("NotAcquired", {}) {} export type LockError = LockTimeoutError | LockCompromisedError diff --git a/packages/util/src/fs-util.ts b/packages/util/src/fs-util.ts index 1f3ed72998..1bbd451d7a 100644 --- a/packages/util/src/fs-util.ts +++ b/packages/util/src/fs-util.ts @@ -11,7 +11,7 @@ import { makeGlobalNode } from "./effect/app-node.js" import { filesystem } from "./effect/app-node-platform.js" export namespace FSUtil { - export class FileSystemError extends Schema.TaggedErrorClass()("FileSystemError", { + export class FileSystemError extends Schema.TaggedError()("FileSystemError", { method: Schema.String, cause: Schema.optional(Schema.Defect()), }) { diff --git a/packages/util/src/npm.ts b/packages/util/src/npm.ts index 26080ce50f..7915165e00 100644 --- a/packages/util/src/npm.ts +++ b/packages/util/src/npm.ts @@ -13,7 +13,7 @@ import { makeRuntime } from "./effect/runtime.js" import { NpmConfig } from "./npm-config.js" import { resolveModule } from "#runtime-import" -export class InstallFailedError extends Schema.TaggedErrorClass()("NpmInstallFailedError", { +export class InstallFailedError extends Schema.TaggedError()("NpmInstallFailedError", { add: Schema.Array(Schema.String).pipe(Schema.optional), dir: Schema.String, cause: Schema.optional(Schema.Defect()), diff --git a/packages/util/src/observability.ts b/packages/util/src/observability.ts index 880a869244..e518fbeccf 100644 --- a/packages/util/src/observability.ts +++ b/packages/util/src/observability.ts @@ -4,7 +4,7 @@ import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem" import { LayerNode } from "./effect/layer-node.js" import { Effect, Layer, Logger, References, Schema } from "effect" import { FetchHttpClient } from "effect/unstable/http" -import { OtlpSerialization } from "effect/unstable/observability" +import { OtlpExporter, OtlpSerialization } from "effect/unstable/observability" import { Logging } from "./observability/logging.js" import { Otlp } from "./observability/otlp.js" @@ -42,6 +42,7 @@ export function layer( Layer.provide(NodeFileSystem.layer), Layer.provide(OtlpSerialization.layerJson), Layer.provide(FetchHttpClient.layer), + Layer.provide(OtlpExporter.layerFlusher), Layer.orDie, Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())), ) diff --git a/packages/util/src/patch.ts b/packages/util/src/patch.ts index 11aadd52bb..76096698d6 100644 --- a/packages/util/src/patch.ts +++ b/packages/util/src/patch.ts @@ -3,7 +3,7 @@ export * as Patch from "./patch.js" import { Result, Schema } from "effect" import { Bom } from "./bom.js" -export class BoundaryError extends Schema.TaggedErrorClass()("Patch.BoundaryError", { +export class BoundaryError extends Schema.TaggedError()("Patch.BoundaryError", { boundary: Schema.Literals(["first", "last"]), }) { override get message() { @@ -11,7 +11,7 @@ export class BoundaryError extends Schema.TaggedErrorClass()("Pat } } -export class InvalidHunkError extends Schema.TaggedErrorClass()("Patch.InvalidHunkError", { +export class InvalidHunkError extends Schema.TaggedError()("Patch.InvalidHunkError", { line: Schema.String, lineNumber: Schema.Number, reason: Schema.optional(Schema.String), diff --git a/packages/util/src/process.ts b/packages/util/src/process.ts index 790bfa3be4..406419921b 100644 --- a/packages/util/src/process.ts +++ b/packages/util/src/process.ts @@ -5,7 +5,7 @@ import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner import { CrossSpawnSpawner } from "./cross-spawn-spawner.js" import { makeGlobalNode } from "./effect/app-node.js" -export class AppProcessError extends Schema.TaggedErrorClass()("AppProcessError", { +export class AppProcessError extends Schema.TaggedError()("AppProcessError", { command: Schema.String, exitCode: Schema.optional(Schema.Number), stderr: Schema.optional(Schema.String), diff --git a/patches/drizzle-orm@1.0.0-rc.2.patch b/patches/drizzle-orm@1.0.0-rc.2.patch new file mode 100644 index 0000000000..787823e60c --- /dev/null +++ b/patches/drizzle-orm@1.0.0-rc.2.patch @@ -0,0 +1,42 @@ +diff --git a/cache/core/cache-effect.cjs b/cache/core/cache-effect.cjs +--- a/cache/core/cache-effect.cjs ++++ b/cache/core/cache-effect.cjs +@@ -103,1 +103,1 @@ +-var EffectCacheError = class extends effect_Schema.TaggedErrorClass()("EffectCacheError", { cause: effect_Schema.Unknown }) { ++var EffectCacheError = class extends effect_Schema.TaggedError()("EffectCacheError", { cause: effect_Schema.Unknown }) { +diff --git a/cache/core/cache-effect.js b/cache/core/cache-effect.js +--- a/cache/core/cache-effect.js ++++ b/cache/core/cache-effect.js +@@ -97,1 +97,1 @@ +-var EffectCacheError = class extends Schema.TaggedErrorClass()("EffectCacheError", { cause: Schema.Unknown }) { ++var EffectCacheError = class extends Schema.TaggedError()("EffectCacheError", { cause: Schema.Unknown }) { +diff --git a/effect-core/errors.cjs b/effect-core/errors.cjs +--- a/effect-core/errors.cjs ++++ b/effect-core/errors.cjs +@@ -8,1 +8,1 @@ +-var EffectDrizzleError = class extends effect_Schema.TaggedErrorClass()("EffectDrizzleError", { ++var EffectDrizzleError = class extends effect_Schema.TaggedError()("EffectDrizzleError", { +@@ -14,1 +14,1 @@ +-var EffectDrizzleQueryError = class EffectDrizzleQueryError extends effect_Schema.TaggedErrorClass()("EffectDrizzleQueryError", { ++var EffectDrizzleQueryError = class EffectDrizzleQueryError extends effect_Schema.TaggedError()("EffectDrizzleQueryError", { +@@ -28,1 +28,1 @@ +-var EffectTransactionRollbackError = class extends effect_Schema.TaggedErrorClass()("EffectTransactionRollbackError", {}) { ++var EffectTransactionRollbackError = class extends effect_Schema.TaggedError()("EffectTransactionRollbackError", {}) { +@@ -32,1 +32,1 @@ +-var MigratorInitError = class extends effect_Schema.TaggedErrorClass()("MigratorInitError", { exitCode: effect_Schema.Literals(["databaseMigrations", "localMigrations"]) }) { ++var MigratorInitError = class extends effect_Schema.TaggedError()("MigratorInitError", { exitCode: effect_Schema.Literals(["databaseMigrations", "localMigrations"]) }) { +diff --git a/effect-core/errors.js b/effect-core/errors.js +--- a/effect-core/errors.js ++++ b/effect-core/errors.js +@@ -5,1 +5,1 @@ +-var EffectDrizzleError = class extends Schema.TaggedErrorClass()("EffectDrizzleError", { ++var EffectDrizzleError = class extends Schema.TaggedError()("EffectDrizzleError", { +@@ -11,1 +11,1 @@ +-var EffectDrizzleQueryError = class EffectDrizzleQueryError extends Schema.TaggedErrorClass()("EffectDrizzleQueryError", { ++var EffectDrizzleQueryError = class EffectDrizzleQueryError extends Schema.TaggedError()("EffectDrizzleQueryError", { +@@ -25,1 +25,1 @@ +-var EffectTransactionRollbackError = class extends Schema.TaggedErrorClass()("EffectTransactionRollbackError", {}) { ++var EffectTransactionRollbackError = class extends Schema.TaggedError()("EffectTransactionRollbackError", {}) { +@@ -29,1 +29,1 @@ +-var MigratorInitError = class extends Schema.TaggedErrorClass()("MigratorInitError", { exitCode: Schema.Literals(["databaseMigrations", "localMigrations"]) }) { ++var MigratorInitError = class extends Schema.TaggedError()("MigratorInitError", { exitCode: Schema.Literals(["databaseMigrations", "localMigrations"]) }) { diff --git a/patches/effect@4.0.0-beta.101.patch b/patches/effect@4.0.0-beta.101.patch deleted file mode 100644 index b2df04e435..0000000000 --- a/patches/effect@4.0.0-beta.101.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/dist/Deferred.js b/dist/Deferred.js -index dd5334d6e42b0881f411fca56688e639cd49c176..ea200a80d6186f07a29d0d231ff1f038433bfec3 100644 ---- a/dist/Deferred.js -+++ b/dist/Deferred.js -@@ -81,8 +81,12 @@ const _await = self => internalEffect.callback(resume => { - self.resumes ??= []; - self.resumes.push(resume); - return internalEffect.sync(() => { -+ // Completion resumes every waiter and clears the array, so a cleanup -+ // that runs after completion (an interrupt racing the resume) has -+ // nothing to unregister. -+ if (!self.resumes) return; - const index = self.resumes.indexOf(resume); -- self.resumes.splice(index, 1); -+ if (index >= 0) self.resumes.splice(index, 1); - }); - }); - export { -diff --git a/src/Deferred.ts b/src/Deferred.ts -index f6d37948bfbe690a7998b06c562e434e1b8ae084..da91e4dc0fd32e534fbc72f7beb0514e67e4ce74 100644 ---- a/src/Deferred.ts -+++ b/src/Deferred.ts -@@ -188,8 +188,12 @@ const _await = (self: Deferred): Effect => - self.resumes ??= [] - self.resumes.push(resume) - return internalEffect.sync(() => { -- const index = self.resumes!.indexOf(resume) -- self.resumes!.splice(index, 1) -+ // Completion resumes every waiter and clears the array, so a cleanup -+ // that runs after completion (an interrupt racing the resume) has -+ // nothing to unregister. -+ if (!self.resumes) return -+ const index = self.resumes.indexOf(resume) -+ if (index >= 0) self.resumes.splice(index, 1) - }) - }) -