Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0e65ee8fb | ||
|
|
a47a1d7cd2 | ||
|
|
94c9f366ec | ||
|
|
4ead2614a5 | ||
|
|
15c644ecb4 | ||
|
|
973a3b570b | ||
|
|
20591148f2 | ||
|
|
75e485c095 | ||
|
|
0d3ea96bb7 | ||
|
|
583ae4ff26 | ||
|
|
4aed5b1daa | ||
|
|
cf1acfd2fa | ||
|
|
6f97cea63b | ||
|
|
4270fcc9c2 | ||
|
|
c86ee984ba | ||
|
|
05deab90ed | ||
|
|
643cca88e3 | ||
|
|
54900febfc | ||
|
|
c73650371b | ||
|
|
15406155aa | ||
|
|
abfaa5210b | ||
|
|
fbf47807fb | ||
|
|
67146125dc | ||
|
|
8ba230e2fb | ||
|
|
12e1821cc7 | ||
|
|
63e66ca3e6 | ||
|
|
cc782a0cc8 |
No files matched your search
@@ -36,4 +36,3 @@ RELEASE_REVIEW.md
|
||||
logs/
|
||||
*.bun-build
|
||||
tsconfig.tsbuildinfo
|
||||
/artifacts/
|
||||
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
.remotion
|
||||
out/frame-*.png
|
||||
@@ -0,0 +1,483 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "glm52-rise-video",
|
||||
"dependencies": {
|
||||
"@remotion/cli": "^4.0.384",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"remotion": "^4.0.384",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.8",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"typescript": "^5.8.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.24.1", "", { "bin": "./bin/babel-parser.js" }, "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.24.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w=="],
|
||||
|
||||
"@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@mediabunny/aac-encoder": ["@mediabunny/aac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JNzgdJoHMFFnv5imi1+dmjZMudsJ1zNCUCEkKjBh90cqGhAFg8xu4V2gsyxE2i6oq/YpWx23P+OvoANLSMcDzA=="],
|
||||
|
||||
"@mediabunny/flac-encoder": ["@mediabunny/flac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-VpKmJO0xlYcFCRD6JvJlMbNQ6d/6YMHdO1gFIqWlZABHjSSL6BquNNEgWSCv5vdF8ELDBwIYBVZEslakIB/7GA=="],
|
||||
|
||||
"@mediabunny/mp3-encoder": ["@mediabunny/mp3-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JyzZyGeGRm2HVUQaGJ/VZT9OG+kG00mA8SLP/f3CO7+qWAmBncKc16WYXWHbZEo8Jn/ZGA6De32S5R2bTQbDqA=="],
|
||||
|
||||
"@module-federation/error-codes": ["@module-federation/error-codes@0.22.0", "", {}, "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug=="],
|
||||
|
||||
"@module-federation/runtime": ["@module-federation/runtime@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/runtime-core": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA=="],
|
||||
|
||||
"@module-federation/runtime-core": ["@module-federation/runtime-core@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA=="],
|
||||
|
||||
"@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/webpack-bundler-runtime": "0.22.0" } }, "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA=="],
|
||||
|
||||
"@module-federation/sdk": ["@module-federation/sdk@0.22.0", "", {}, "sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g=="],
|
||||
|
||||
"@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="],
|
||||
|
||||
"@remotion/bundler": ["@remotion/bundler@4.0.483", "", { "dependencies": { "@remotion/media-parser": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@rspack/core": "1.7.11", "@rspack/plugin-react-refresh": "1.6.1", "css-loader": "7.1.4", "esbuild": "0.28.1", "react-refresh": "0.18.0", "remotion": "4.0.483", "style-loader": "4.0.0", "webpack": "5.105.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-5fQRMYgr2sxZPBOThnIVuFwHBq/FhusJ+Ke6xopga8io8ecK/mj9GaRXC3tgfMa+YWuu8ZSXZ0U9EsMZjjP5YQ=="],
|
||||
|
||||
"@remotion/canvas-capture": ["@remotion/canvas-capture@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JABgbfvXwjFp1E61tlDN9gVAH8OoeF4kUUELNwG9kcNOE4ex8+vCYEO6VKIaXZ4l8A1PEAQ5EK//NheTJ80gfw=="],
|
||||
|
||||
"@remotion/cli": ["@remotion/cli@4.0.483", "", { "dependencies": { "@remotion/bundler": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-server": "4.0.483", "@remotion/studio-shared": "4.0.483", "dotenv": "17.3.1", "minimist": "1.2.6", "prompts": "2.4.2", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" }, "bin": { "remotion": "remotion-cli.js", "remotionb": "remotionb-cli.js", "remotiond": "remotiond-cli.js" } }, "sha512-z4TQcgTfQbSIV4GQpCvIihDL77M+leQelbxv962PmfSKTT7z3XnNN732PcZ4sei2+Xg+d2SD95K4tI5XBYs5Gw=="],
|
||||
|
||||
"@remotion/compositor-darwin-arm64": ["@remotion/compositor-darwin-arm64@4.0.483", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CkEJXouGEoCs5PX3KOufkXrlT/Kgn0ZF7SEQ4meCYGYMZD+QPVtsmS1MXH8pQ4RHlFO6Tk7g0CIHMT3Y4yzpuA=="],
|
||||
|
||||
"@remotion/compositor-darwin-x64": ["@remotion/compositor-darwin-x64@4.0.483", "", { "os": "darwin", "cpu": "x64" }, "sha512-vDZK5U8FYbHGMjFC2lUgJRBz8KXwbwFSvEQi8FATD0roNg75SoaEJWrqAOIVv8v5eBjPvo18znDc36NLRYn1Eg=="],
|
||||
|
||||
"@remotion/compositor-linux-arm64-gnu": ["@remotion/compositor-linux-arm64-gnu@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-1LzfYDY/DQxy3MIc9pCbTn1ObcBDcyI6MzODOwe1bTZl8TZxdUUt1M3hDrQ60AB6iHwruBAnzT9dnogiMIdSew=="],
|
||||
|
||||
"@remotion/compositor-linux-arm64-musl": ["@remotion/compositor-linux-arm64-musl@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-nG1btxg0HXuLzulIqAg9NnxWyewZNrA0iLe82HdniaJjeWLORreGo4cEEJz1SjbDpQuPEY562XGkTO2DLKK5mA=="],
|
||||
|
||||
"@remotion/compositor-linux-x64-gnu": ["@remotion/compositor-linux-x64-gnu@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-CV4h6r2rNYh4P8utUzP6RM2vW2vq43nA3IvVOwRSuh9LwJh/7rwG53Oco4HanY/sstaNuymGpT57wdXwONU5CQ=="],
|
||||
|
||||
"@remotion/compositor-linux-x64-musl": ["@remotion/compositor-linux-x64-musl@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-moKvavbkoz5nteJZA4K6LMgTTlewhwIbtO7DYARZ3LK3ClGUKnYfFcmaPS15hMun02JPTOMIWbrlaszdR75mxA=="],
|
||||
|
||||
"@remotion/compositor-win32-x64-msvc": ["@remotion/compositor-win32-x64-msvc@4.0.483", "", { "os": "win32", "cpu": "x64" }, "sha512-eDpWe6Vy7ySHugwxlgaeohqdBwR1etxiymXzT13cgbPw2+p6d55z1tJ7VPTXyfu0o+UdyRTauWqD4msoxN0wow=="],
|
||||
|
||||
"@remotion/licensing": ["@remotion/licensing@4.0.483", "", {}, "sha512-GRtjykrxMmB5Cjpq1oVqeYIRXI95vid6afX0LTLfp1shD6MR4lTZRoRuopxrrZp1E4XFGXoY64b6dlIudgTyBQ=="],
|
||||
|
||||
"@remotion/media-parser": ["@remotion/media-parser@4.0.483", "", {}, "sha512-iva9Eof7QQX+3hGxH/N8pGi80wgdGuzOr825Zn7IuEe7IWdtRYWlFpCEghmyfhrwgaWa7RY51wg77ycR3c3nRg=="],
|
||||
|
||||
"@remotion/media-utils": ["@remotion/media-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4T4WQh/U95kCBzgmz/EL/HL8Zeox/AKAL5ufsehrZFgwlcvH1EsKNJH/RWaAtNPRLF+pskEOgFzPYaczHeI8hg=="],
|
||||
|
||||
"@remotion/player": ["@remotion/player@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yyIQ9vinUqqS0fQeL52bPCWQIr8qDXCqQ4iys8P7dSZncdu8V29p4W2a0/4eKV8bv5+mjnJQ/U6nl9NxBF1hdA=="],
|
||||
|
||||
"@remotion/renderer": ["@remotion/renderer@4.0.483", "", { "dependencies": { "@remotion/licensing": "4.0.483", "@remotion/streaming": "4.0.483", "execa": "5.1.1", "remotion": "4.0.483", "source-map": "0.8.0-beta.0", "ws": "8.21.0" }, "optionalDependencies": { "@remotion/compositor-darwin-arm64": "4.0.483", "@remotion/compositor-darwin-x64": "4.0.483", "@remotion/compositor-linux-arm64-gnu": "4.0.483", "@remotion/compositor-linux-arm64-musl": "4.0.483", "@remotion/compositor-linux-x64-gnu": "4.0.483", "@remotion/compositor-linux-x64-musl": "4.0.483", "@remotion/compositor-win32-x64-msvc": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-eSKdQqm8rcl+GNyOhFsBgcPYWMcxTJWHL5xaNrd037piCaL3sdJ57OEO/AbfEvvOO14zwUvlsONKjlkLlEVyKg=="],
|
||||
|
||||
"@remotion/streaming": ["@remotion/streaming@4.0.483", "", {}, "sha512-96rqrk+l5AfriHOqmqxMn8rI6UJfFY7r5UMDZoSKqXWzTOwj+0VWHTRl9ilZQMXhYACaMSA/5yrL9jgQEK8Yuw=="],
|
||||
|
||||
"@remotion/studio": ["@remotion/studio@4.0.483", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.31", "@remotion/canvas-capture": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@remotion/web-renderer": "4.0.483", "@remotion/zod-types": "4.0.483", "mediabunny": "1.47.0", "memfs": "3.4.3", "open": "8.4.2", "remotion": "4.0.483", "semver": "7.5.3", "zod": "4.3.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-gNa1Lw8NmHl0jwFb5fk7rzA+WFTJQpGDT/49A38t9jpEwoF+h1mKTgY8gA202apzjBHrEECdFE450npnBOUpUw=="],
|
||||
|
||||
"@remotion/studio-server": ["@remotion/studio-server@4.0.483", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", "@remotion/bundler": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "memfs": "3.4.3", "open": "8.4.2", "prettier": "3.8.1", "recast": "0.23.11", "remotion": "4.0.483", "semver": "7.5.3" } }, "sha512-2FSLbVN5N8bgtQPX+RQRbis557tJJnVTOZuEBZndfC9NOoPdARlSgEnwVer9tBNczUlc6B3KrPxyPSlS3UjL+Q=="],
|
||||
|
||||
"@remotion/studio-shared": ["@remotion/studio-shared@4.0.483", "", { "dependencies": { "remotion": "4.0.483" } }, "sha512-aXxBYUgsWgphHVq7T7bz+ICMGzfii7pcX1IxS5hbLMLJHqlDtk9g+qcxm4kJ2Fjj/Gb5gERKiNzYym8WZTIM2Q=="],
|
||||
|
||||
"@remotion/timeline-utils": ["@remotion/timeline-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0" } }, "sha512-KTTMdpNA5uRLX+iisAITO+V9cJBk17F8EWvuUnAEVmAFOQTbGIyPI9HNw5pZmL7SlzOJdFjAtksTjipeYGkEug=="],
|
||||
|
||||
"@remotion/web-renderer": ["@remotion/web-renderer@4.0.483", "", { "dependencies": { "@mediabunny/aac-encoder": "1.47.0", "@mediabunny/flac-encoder": "1.47.0", "@mediabunny/mp3-encoder": "1.47.0", "@remotion/licensing": "4.0.483", "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-14iURfVWA/hcF/rJvkid1ZR5nmnVhkTIf071FabCFi6kdViOSVBugSglJ8tUPvWVbWmxlXGDGQD9CSU18IATww=="],
|
||||
|
||||
"@remotion/zod-types": ["@remotion/zod-types@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "zod": "4.3.6" } }, "sha512-KIVYIzFpZBDB0wxGGQu5tDBr4XOYRzvrPXjmo6O/FI5Xx7O8hgvJmBs9VDkEwonAOft86sg79hI19F1DTX1p4w=="],
|
||||
|
||||
"@rspack/binding": ["@rspack/binding@1.7.11", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.7.11", "@rspack/binding-darwin-x64": "1.7.11", "@rspack/binding-linux-arm64-gnu": "1.7.11", "@rspack/binding-linux-arm64-musl": "1.7.11", "@rspack/binding-linux-x64-gnu": "1.7.11", "@rspack/binding-linux-x64-musl": "1.7.11", "@rspack/binding-wasm32-wasi": "1.7.11", "@rspack/binding-win32-arm64-msvc": "1.7.11", "@rspack/binding-win32-ia32-msvc": "1.7.11", "@rspack/binding-win32-x64-msvc": "1.7.11" } }, "sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q=="],
|
||||
|
||||
"@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.7.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig=="],
|
||||
|
||||
"@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.7.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA=="],
|
||||
|
||||
"@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA=="],
|
||||
|
||||
"@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw=="],
|
||||
|
||||
"@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ=="],
|
||||
|
||||
"@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg=="],
|
||||
|
||||
"@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.7.11", "", { "dependencies": { "@napi-rs/wasm-runtime": "1.0.7" }, "cpu": "none" }, "sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ=="],
|
||||
|
||||
"@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.7.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA=="],
|
||||
|
||||
"@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.7.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw=="],
|
||||
|
||||
"@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.7.11", "", { "os": "win32", "cpu": "x64" }, "sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q=="],
|
||||
|
||||
"@rspack/core": ["@rspack/core@1.7.11", "", { "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.11", "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew=="],
|
||||
|
||||
"@rspack/lite-tapable": ["@rspack/lite-tapable@1.1.0", "", {}, "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw=="],
|
||||
|
||||
"@rspack/plugin-react-refresh": ["@rspack/plugin-react-refresh@1.6.1", "", { "dependencies": { "error-stack-parser": "^2.1.4", "html-entities": "^2.6.0" }, "peerDependencies": { "react-refresh": ">=0.10.0 <1.0.0", "webpack-hot-middleware": "2.x" }, "optionalPeers": ["webpack-hot-middleware"] }, "sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw=="],
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
||||
|
||||
"@types/dom-mediacapture-transform": ["@types/dom-mediacapture-transform@0.1.11", "", { "dependencies": { "@types/dom-webcodecs": "*" } }, "sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ=="],
|
||||
|
||||
"@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="],
|
||||
|
||||
"@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="],
|
||||
|
||||
"@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/node": ["@types/node@26.0.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="],
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||
|
||||
"@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="],
|
||||
|
||||
"@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="],
|
||||
|
||||
"@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="],
|
||||
|
||||
"@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="],
|
||||
|
||||
"@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="],
|
||||
|
||||
"@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="],
|
||||
|
||||
"@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="],
|
||||
|
||||
"@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="],
|
||||
|
||||
"@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="],
|
||||
|
||||
"@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="],
|
||||
|
||||
"@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="],
|
||||
|
||||
"@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="],
|
||||
|
||||
"@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="],
|
||||
|
||||
"@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="],
|
||||
|
||||
"@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="],
|
||||
|
||||
"@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="],
|
||||
|
||||
"@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="],
|
||||
|
||||
"acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
|
||||
|
||||
"acorn-import-phases": ["acorn-import-phases@1.0.4", "", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="],
|
||||
|
||||
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
||||
|
||||
"ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||
|
||||
"ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="],
|
||||
|
||||
"ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.40", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw=="],
|
||||
|
||||
"browserslist": ["browserslist@4.28.4", "", { "dependencies": { "baseline-browser-mapping": "^2.10.38", "caniuse-lite": "^1.0.30001799", "electron-to-chromium": "^1.5.376", "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw=="],
|
||||
|
||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="],
|
||||
|
||||
"chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
|
||||
|
||||
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"css-loader": ["css-loader@7.1.4", "", { "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.40", "postcss-modules-extract-imports": "^3.1.0", "postcss-modules-local-by-default": "^4.0.5", "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.6.3" }, "peerDependencies": { "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "webpack": "^5.27.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw=="],
|
||||
|
||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
|
||||
|
||||
"dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.379", "", {}, "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.24.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw=="],
|
||||
|
||||
"error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="],
|
||||
|
||||
"es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="],
|
||||
|
||||
"esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="],
|
||||
|
||||
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
"estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="],
|
||||
|
||||
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
||||
|
||||
"execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
|
||||
|
||||
"fs-monkey": ["fs-monkey@1.0.3", "", {}, "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="],
|
||||
|
||||
"get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
|
||||
|
||||
"glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
|
||||
|
||||
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
||||
|
||||
"icss-utils": ["icss-utils@5.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="],
|
||||
|
||||
"is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
||||
|
||||
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
||||
|
||||
"is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
||||
|
||||
"loader-runner": ["loader-runner@4.3.2", "", {}, "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w=="],
|
||||
|
||||
"lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="],
|
||||
|
||||
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
|
||||
|
||||
"mediabunny": ["mediabunny@1.47.0", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-XQMZAcaKPkJ7hQ/Q2fvBdl3ZazQl2WVxDysUbJWh4PuAnLoerdsQBdPTDWdUdK6hh26LQ8Ue94MLLnmpWvlUYg=="],
|
||||
|
||||
"memfs": ["memfs@3.4.3", "", { "dependencies": { "fs-monkey": "1.0.3" } }, "sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg=="],
|
||||
|
||||
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"minimist": ["minimist@1.2.6", "", {}, "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
|
||||
|
||||
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.50", "", {}, "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
|
||||
"open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
|
||||
|
||||
"postcss-modules-extract-imports": ["postcss-modules-extract-imports@3.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q=="],
|
||||
|
||||
"postcss-modules-local-by-default": ["postcss-modules-local-by-default@4.2.0", "", { "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw=="],
|
||||
|
||||
"postcss-modules-scope": ["postcss-modules-scope@3.2.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA=="],
|
||||
|
||||
"postcss-modules-values": ["postcss-modules-values@4.0.0", "", { "dependencies": { "icss-utils": "^5.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="],
|
||||
|
||||
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
|
||||
|
||||
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
|
||||
|
||||
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"react": ["react@19.2.7", "", {}, "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.7", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.7" } }, "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ=="],
|
||||
|
||||
"react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
|
||||
|
||||
"recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
|
||||
|
||||
"remotion": ["remotion@4.0.483", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-lf4xq4Twn75TQeTavFLrTE4zdck7EKBSx07ZrPv4om40Sist+3G0kq7NNzSjMeJ6G2Wx6vI+0oICD/vv4sGWtg=="],
|
||||
|
||||
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
||||
|
||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="],
|
||||
|
||||
"semver": ["semver@7.5.3", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
|
||||
"source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||
|
||||
"stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
|
||||
|
||||
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
||||
|
||||
"style-loader": ["style-loader@4.0.0", "", { "peerDependencies": { "webpack": "^5.27.0" } }, "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA=="],
|
||||
|
||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||
|
||||
"terser": ["terser@5.48.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q=="],
|
||||
|
||||
"terser-webpack-plugin": ["terser-webpack-plugin@5.6.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ=="],
|
||||
|
||||
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
|
||||
|
||||
"to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="],
|
||||
|
||||
"tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
|
||||
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"watchpack": ["watchpack@2.5.2", "", { "dependencies": { "graceful-fs": "^4.1.2" } }, "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg=="],
|
||||
|
||||
"webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
|
||||
|
||||
"webpack": ["webpack@5.105.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.19.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.16", "watchpack": "^2.5.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw=="],
|
||||
|
||||
"webpack-sources": ["webpack-sources@3.5.0", "", {}, "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ=="],
|
||||
|
||||
"whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||
|
||||
"css-loader/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "glm52-rise-video",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"render": "remotion render src/index.tsx GLM52Rise out/glm-52-broke-out.mp4 --codec h264 --pixel-format yuv420p",
|
||||
"render:sheep": "remotion render src/index.tsx NZSheep out/nz-sheep.mp4 --codec h264 --pixel-format yuv420p",
|
||||
"render:novel": "remotion render src/index.tsx NovelTokens out/novel-1984.mp4 --codec h264 --pixel-format yuv420p",
|
||||
"render:flash": "remotion render src/index.tsx FlashShare out/flash-share.mp4 --codec h264 --pixel-format yuv420p",
|
||||
"render:minimax": "remotion render src/index.tsx MiniMaxClimb out/minimax-climb.mp4 --codec h264 --pixel-format yuv420p",
|
||||
"still:june": "remotion still src/index.tsx JuneTotals out/june-totals.png --frame=0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@remotion/cli": "^4.0.384",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"remotion": "^4.0.384"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.8",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 172 KiB |
@@ -0,0 +1,156 @@
|
||||
// Verified against the production opencode-stats PlanetScale DB.
|
||||
// Scope: tier='Go' (OpenCode Go), dataset='zen', client='all', source='all', grain='day'.
|
||||
// metric = total_tokens. Daily token volume per model; GLM-5.2 (zhipu) launched Jun 17.
|
||||
// Segments per day (tokens): glm-5.2, deepseek-v4-flash, deepseek-v4-pro, minimax-m3, all others.
|
||||
|
||||
export type Day = {
|
||||
date: string
|
||||
total: number
|
||||
glm: number
|
||||
dsf: number
|
||||
dsp: number
|
||||
mm: number
|
||||
others: number
|
||||
}
|
||||
|
||||
export const days: Day[] = [
|
||||
{
|
||||
date: "Jun 12",
|
||||
total: 2_283_799_449_383,
|
||||
glm: 0,
|
||||
dsf: 1_176_701_653_509,
|
||||
dsp: 569_527_034_307,
|
||||
mm: 159_016_250_684,
|
||||
others: 378_554_510_883,
|
||||
},
|
||||
{
|
||||
date: "Jun 13",
|
||||
total: 2_008_462_388_420,
|
||||
glm: 0,
|
||||
dsf: 995_338_131_997,
|
||||
dsp: 445_817_536_548,
|
||||
mm: 211_743_241_967,
|
||||
others: 355_563_477_908,
|
||||
},
|
||||
{
|
||||
date: "Jun 14",
|
||||
total: 2_007_785_405_251,
|
||||
glm: 0,
|
||||
dsf: 983_954_176_228,
|
||||
dsp: 428_151_999_341,
|
||||
mm: 262_476_527_930,
|
||||
others: 333_202_701_752,
|
||||
},
|
||||
{
|
||||
date: "Jun 15",
|
||||
total: 2_694_736_103_062,
|
||||
glm: 0,
|
||||
dsf: 1_255_893_953_859,
|
||||
dsp: 632_223_338_376,
|
||||
mm: 352_507_442_991,
|
||||
others: 454_111_367_836,
|
||||
},
|
||||
{
|
||||
date: "Jun 16",
|
||||
total: 2_838_153_758_908,
|
||||
glm: 0,
|
||||
dsf: 1_336_625_283_800,
|
||||
dsp: 676_480_415_730,
|
||||
mm: 305_268_829_013,
|
||||
others: 519_779_230_365,
|
||||
},
|
||||
{
|
||||
date: "Jun 17",
|
||||
total: 2_778_964_711_109,
|
||||
glm: 70_095_977_043,
|
||||
dsf: 1_339_831_523_555,
|
||||
dsp: 660_414_395_220,
|
||||
mm: 251_302_096_157,
|
||||
others: 457_320_719_134,
|
||||
},
|
||||
{
|
||||
date: "Jun 18",
|
||||
total: 2_806_992_430_656,
|
||||
glm: 201_130_231_172,
|
||||
dsf: 1_295_599_996_869,
|
||||
dsp: 595_665_008_776,
|
||||
mm: 322_205_104_324,
|
||||
others: 392_392_089_515,
|
||||
},
|
||||
{
|
||||
date: "Jun 19",
|
||||
total: 2_419_611_630_232,
|
||||
glm: 199_086_413_910,
|
||||
dsf: 1_115_750_468_802,
|
||||
dsp: 475_965_869_304,
|
||||
mm: 303_586_698_735,
|
||||
others: 325_222_179_481,
|
||||
},
|
||||
{
|
||||
date: "Jun 20",
|
||||
total: 2_188_278_916_865,
|
||||
glm: 193_931_516_396,
|
||||
dsf: 1_050_194_681_012,
|
||||
dsp: 395_303_435_278,
|
||||
mm: 281_998_000_337,
|
||||
others: 266_851_283_842,
|
||||
},
|
||||
{
|
||||
date: "Jun 21",
|
||||
total: 2_042_309_961_344,
|
||||
glm: 181_894_043_118,
|
||||
dsf: 985_164_570_580,
|
||||
dsp: 368_194_079_542,
|
||||
mm: 259_812_551_324,
|
||||
others: 247_244_716_780,
|
||||
},
|
||||
{
|
||||
date: "Jun 22",
|
||||
total: 2_893_934_325_663,
|
||||
glm: 301_759_048_475,
|
||||
dsf: 1_298_124_282_989,
|
||||
dsp: 581_012_596_194,
|
||||
mm: 371_581_117_839,
|
||||
others: 341_457_280_166,
|
||||
},
|
||||
{
|
||||
date: "Jun 23",
|
||||
total: 3_109_009_321_480,
|
||||
glm: 282_277_235_158,
|
||||
dsf: 1_423_571_678_821,
|
||||
dsp: 627_374_654_587,
|
||||
mm: 429_416_300_508,
|
||||
others: 346_369_452_406,
|
||||
},
|
||||
{
|
||||
date: "Jun 24",
|
||||
total: 2_939_149_971_595,
|
||||
glm: 256_497_442_533,
|
||||
dsf: 1_373_583_023_234,
|
||||
dsp: 601_270_997_775,
|
||||
mm: 391_586_493_231,
|
||||
others: 316_212_014_822,
|
||||
},
|
||||
{
|
||||
date: "Jun 25",
|
||||
total: 3_029_641_552_948,
|
||||
glm: 256_279_657_734,
|
||||
dsf: 1_481_084_002_776,
|
||||
dsp: 602_077_167_287,
|
||||
mm: 375_985_302_874,
|
||||
others: 314_215_422_277,
|
||||
},
|
||||
]
|
||||
|
||||
export const launchIndex = 5 // Jun 17, first day of GLM-5.2 usage
|
||||
// GLM-5.2 weekly token volume, Jun 19-25 (sum of glm): 1,671,725,357,324 = 1.67T
|
||||
export const glmWeekTokensT = 1.672
|
||||
|
||||
// stacked segments, bottom -> top. GLM-5.2 is the hero (blue); the rest are the field it cut into.
|
||||
export const segments = [
|
||||
{ key: "glm", label: "GLM-5.2", color: "#3b5cf6", hero: true },
|
||||
{ key: "dsf", label: "deepseek-v4-flash", color: "#9ca3ad" },
|
||||
{ key: "dsp", label: "deepseek-v4-pro", color: "#b3b9c1" },
|
||||
{ key: "mm", label: "minimax-m3", color: "#c8cdd3" },
|
||||
{ key: "others", label: "other models", color: "#dde0e4" },
|
||||
] as const
|
||||
@@ -0,0 +1,185 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill, Easing, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"
|
||||
|
||||
// stats.opencode.ai design tokens (light theme)
|
||||
const c = {
|
||||
bg: "#ffffff",
|
||||
ink: "#161616",
|
||||
muted: "#5c5c5c",
|
||||
faint: "#808080",
|
||||
line: "#e6e6e6",
|
||||
dot: "#e4e4e4",
|
||||
gray: "#aab0b8",
|
||||
accent: "#3b5cf6",
|
||||
accentHi: "#5b78ff",
|
||||
}
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
|
||||
const DOT_MASK =
|
||||
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
|
||||
|
||||
// verified: OpenCode Go, week of Jun 22-28, 2026 (2026-W26). share = % of 19.64T total Go tokens.
|
||||
const bars = [
|
||||
{ label: "deepseek-v4-flash", share: 48.3, hero: true },
|
||||
{ label: "deepseek-v4-pro", share: 19.4 },
|
||||
{ label: "minimax-m3", share: 13.0 },
|
||||
{ label: "glm-5.2", share: 8.3 },
|
||||
{ label: "mimo-v2.5", share: 4.3 },
|
||||
{ label: "kimi-k2.7-code", share: 2.6 },
|
||||
{ label: "other models", share: 4.1 },
|
||||
]
|
||||
|
||||
function DataWordmark({ height = 30 }: { height?: number }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
|
||||
<path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function FlashShare() {
|
||||
const frame = useCurrentFrame()
|
||||
const { fps } = useVideoConfig()
|
||||
|
||||
const grow = (i: number) =>
|
||||
Math.min(
|
||||
1,
|
||||
Math.max(0, spring({ frame: frame - 18 - i * 7, fps, config: { damping: 18, stiffness: 120, mass: 0.6 } })),
|
||||
)
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
|
||||
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 22–28, 2026</div>
|
||||
</div>
|
||||
|
||||
{/* headline (static) */}
|
||||
<div style={{ marginTop: 50 }}>
|
||||
<div style={{ fontSize: 23, fontWeight: 600, color: c.muted, letterSpacing: 2 }}>
|
||||
OPENCODE GO · SHARE OF TOKENS
|
||||
</div>
|
||||
<div
|
||||
style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 24, marginTop: 14 }}
|
||||
>
|
||||
<div style={{ fontSize: 62, fontWeight: 600, letterSpacing: -2, lineHeight: 1 }}>DeepSeek V4 Flash</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 88,
|
||||
fontWeight: 600,
|
||||
letterSpacing: -2,
|
||||
lineHeight: 1,
|
||||
color: c.accent,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
48%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* bar chart */}
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", gap: 16 }}>
|
||||
{bars.map((b, i) => {
|
||||
const g = grow(i)
|
||||
const pct = b.share * g
|
||||
return (
|
||||
<div key={b.label} style={{ display: "flex", alignItems: "center", gap: 18 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 268,
|
||||
fontSize: 23,
|
||||
fontWeight: b.hero ? 600 : 500,
|
||||
color: b.hero ? c.ink : c.muted,
|
||||
textAlign: "right",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
{b.label}
|
||||
</div>
|
||||
<div style={{ position: "relative", flex: 1, height: 48 }}>
|
||||
{/* dotted 100% track — height is a multiple of the 12px tile, anchored bottom, so dots never clip */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
background: c.dot,
|
||||
WebkitMaskImage: DOT_MASK,
|
||||
maskImage: DOT_MASK,
|
||||
WebkitMaskSize: "12px 12px",
|
||||
maskSize: "12px 12px",
|
||||
WebkitMaskRepeat: "repeat",
|
||||
maskRepeat: "repeat",
|
||||
WebkitMaskPosition: "left bottom",
|
||||
maskPosition: "left bottom",
|
||||
}}
|
||||
/>
|
||||
{/* fill */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: `${pct}%`,
|
||||
background: b.hero ? c.accent : c.gray,
|
||||
borderRight: b.hero ? `2px solid ${c.accentHi}` : "none",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: 84,
|
||||
fontSize: 24,
|
||||
fontWeight: b.hero ? 600 : 500,
|
||||
color: b.hero ? c.accent : c.muted,
|
||||
textAlign: "right",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
{Math.round(pct)}%
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* footer */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 24,
|
||||
paddingTop: 22,
|
||||
borderTop: `1px solid ${c.line}`,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
|
||||
<span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
|
||||
DeepSeek V4 Flash · 9.48T tokens · 83.6M requests
|
||||
</div>
|
||||
<div style={{ color: c.ink }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Composition, registerRoot } from "remotion"
|
||||
import { GLM52Rise } from "./video"
|
||||
import { NZSheep } from "./sheep"
|
||||
import { NovelTokens } from "./novel"
|
||||
import { FlashShare } from "./flash"
|
||||
import { MiniMaxClimb } from "./minimax"
|
||||
import { JuneTotals } from "./june"
|
||||
|
||||
function Root() {
|
||||
return (
|
||||
<>
|
||||
<Composition id="GLM52Rise" component={GLM52Rise} durationInFrames={240} fps={30} width={1080} height={1080} />
|
||||
<Composition id="NZSheep" component={NZSheep} durationInFrames={150} fps={30} width={1080} height={1080} />
|
||||
<Composition
|
||||
id="NovelTokens"
|
||||
component={NovelTokens}
|
||||
durationInFrames={150}
|
||||
fps={30}
|
||||
width={1080}
|
||||
height={1080}
|
||||
/>
|
||||
<Composition id="FlashShare" component={FlashShare} durationInFrames={165} fps={30} width={1080} height={1080} />
|
||||
<Composition
|
||||
id="MiniMaxClimb"
|
||||
component={MiniMaxClimb}
|
||||
durationInFrames={165}
|
||||
fps={30}
|
||||
width={1080}
|
||||
height={1080}
|
||||
/>
|
||||
<Composition id="JuneTotals" component={JuneTotals} durationInFrames={1} fps={30} width={1080} height={1080} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
registerRoot(Root)
|
||||
@@ -0,0 +1,144 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill } from "remotion"
|
||||
|
||||
const c = {
|
||||
bg: "#ffffff",
|
||||
ink: "#161616",
|
||||
muted: "#5c5c5c",
|
||||
faint: "#808080",
|
||||
line: "#e6e6e6",
|
||||
dot: "#dcdcdc",
|
||||
accent: "#3b5cf6",
|
||||
}
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
|
||||
const DOT_MASK =
|
||||
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
|
||||
|
||||
// verified: OpenCode Go (tier=Go, dataset=zen), June 1-30, 2026.
|
||||
// 72.78T tokens · 651.4M requests · 11.42M sessions -> rounded headline figures.
|
||||
|
||||
function DataWordmark({ height = 30 }: { height?: number }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
|
||||
<path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function DotBand() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: 12,
|
||||
background: c.dot,
|
||||
WebkitMaskImage: DOT_MASK,
|
||||
maskImage: DOT_MASK,
|
||||
WebkitMaskSize: "12px 12px",
|
||||
maskSize: "12px 12px",
|
||||
WebkitMaskRepeat: "repeat",
|
||||
maskRepeat: "repeat",
|
||||
WebkitMaskPosition: "left top",
|
||||
maskPosition: "left top",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function Metric({ value, label }: { value: string; label: string }) {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 92,
|
||||
fontWeight: 600,
|
||||
letterSpacing: -3,
|
||||
lineHeight: 1,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
marginLeft: -8, // align the glyph's visual left edge to the column
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
<div style={{ marginTop: 16, fontSize: 24, fontWeight: 500, color: c.muted, letterSpacing: 1 }}>{label}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function JuneTotals() {
|
||||
return (
|
||||
<AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
|
||||
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 22 }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>MONTHLY RECAP</div>
|
||||
</div>
|
||||
<DotBand />
|
||||
|
||||
{/* hero */}
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" }}>
|
||||
<div style={{ fontSize: 25, fontWeight: 600, color: c.muted, letterSpacing: 3 }}>OPENCODE GO · JUNE 2026</div>
|
||||
<div style={{ marginTop: 14 }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 300,
|
||||
fontWeight: 600,
|
||||
letterSpacing: -10,
|
||||
lineHeight: 0.82,
|
||||
color: c.accent,
|
||||
marginLeft: -22,
|
||||
}}
|
||||
>
|
||||
73T
|
||||
</div>
|
||||
<div style={{ fontSize: 50, fontWeight: 600, color: c.ink, marginTop: 10 }}>tokens processed</div>
|
||||
</div>
|
||||
|
||||
{/* supporting metrics */}
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
marginTop: 60,
|
||||
paddingTop: 40,
|
||||
borderTop: `1px solid ${c.line}`,
|
||||
}}
|
||||
>
|
||||
<Metric value="650M" label="requests" />
|
||||
<Metric value="11M" label="sessions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* footer */}
|
||||
<DotBand />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
marginTop: 22,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ color: c.ink }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"
|
||||
|
||||
const c = {
|
||||
bg: "#ffffff",
|
||||
ink: "#161616",
|
||||
muted: "#5c5c5c",
|
||||
faint: "#808080",
|
||||
line: "#e6e6e6",
|
||||
dot: "#e4e4e4",
|
||||
accent: "#3b5cf6",
|
||||
accentHi: "#5b78ff",
|
||||
accentDim: "#aebcf3",
|
||||
}
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
|
||||
const DOT_MASK =
|
||||
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
|
||||
|
||||
// verified: minimax-m3, OpenCode Go (tier=Go, dataset=zen), weekly total_tokens.
|
||||
// W26 2.559T is +23.2% / +482.3B vs W25 2.077T.
|
||||
const weeks = [
|
||||
{ label: "May 25", t: 0.008 },
|
||||
{ label: "Jun 1", t: 0.429 },
|
||||
{ label: "Jun 8", t: 1.192 },
|
||||
{ label: "Jun 15", t: 2.077 },
|
||||
{ label: "Jun 22", t: 2.559, latest: true },
|
||||
]
|
||||
const AXIS_MAX = 3.0
|
||||
|
||||
function DataWordmark({ height = 30 }: { height?: number }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
|
||||
<path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const CHART_H = 420 // multiple of 12 so the dotted tracks never clip
|
||||
|
||||
export function MiniMaxClimb() {
|
||||
const frame = useCurrentFrame()
|
||||
const { fps } = useVideoConfig()
|
||||
|
||||
const grow = (i: number) =>
|
||||
Math.min(
|
||||
1,
|
||||
Math.max(0, spring({ frame: frame - 22 - i * 9, fps, config: { damping: 18, stiffness: 110, mass: 0.6 } })),
|
||||
)
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
|
||||
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 22–28, 2026</div>
|
||||
</div>
|
||||
|
||||
{/* headline (static) */}
|
||||
<div style={{ marginTop: 50 }}>
|
||||
<div style={{ fontSize: 23, fontWeight: 600, color: c.muted, letterSpacing: 2 }}>
|
||||
OPENCODE GO · WEEKLY TOKENS
|
||||
</div>
|
||||
<div
|
||||
style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 24, marginTop: 14 }}
|
||||
>
|
||||
<div style={{ fontSize: 62, fontWeight: 600, letterSpacing: -2, lineHeight: 1 }}>MiniMax M3</div>
|
||||
<div style={{ textAlign: "right", flexShrink: 0 }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 84,
|
||||
fontWeight: 600,
|
||||
letterSpacing: -2,
|
||||
lineHeight: 1,
|
||||
color: c.accent,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
+23.2%
|
||||
</div>
|
||||
<div style={{ fontSize: 19, fontWeight: 500, color: c.muted, letterSpacing: 1, marginTop: 6 }}>
|
||||
WEEK OVER WEEK
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* column chart */}
|
||||
<div style={{ flex: 1, display: "flex", alignItems: "flex-end", marginTop: 30 }}>
|
||||
<div style={{ width: "100%", display: "flex", alignItems: "flex-end", gap: 30 }}>
|
||||
{weeks.map((w, i) => {
|
||||
const g = grow(i)
|
||||
const h = Math.round((w.t / AXIS_MAX) * CHART_H * g)
|
||||
return (
|
||||
<div key={w.label} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center" }}>
|
||||
{/* value + bar */}
|
||||
<div style={{ position: "relative", width: "100%", height: CHART_H }}>
|
||||
{/* dotted track */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
background: c.dot,
|
||||
WebkitMaskImage: DOT_MASK,
|
||||
maskImage: DOT_MASK,
|
||||
WebkitMaskSize: "12px 12px",
|
||||
maskSize: "12px 12px",
|
||||
WebkitMaskRepeat: "repeat",
|
||||
maskRepeat: "repeat",
|
||||
WebkitMaskPosition: "left bottom",
|
||||
maskPosition: "left bottom",
|
||||
}}
|
||||
/>
|
||||
{/* fill */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: h,
|
||||
background: w.latest ? c.accent : c.accentDim,
|
||||
borderTop: w.latest ? `3px solid ${c.accentHi}` : "none",
|
||||
}}
|
||||
/>
|
||||
{/* value label */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: h + 10,
|
||||
textAlign: "center",
|
||||
fontSize: 26,
|
||||
fontWeight: w.latest ? 600 : 500,
|
||||
color: w.latest ? c.accent : c.muted,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
opacity: interpolate(g, [0.5, 1], [0, 1], {
|
||||
extrapolateLeft: "clamp",
|
||||
extrapolateRight: "clamp",
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{w.t.toFixed(2)}T
|
||||
</div>
|
||||
</div>
|
||||
{/* week label */}
|
||||
<div
|
||||
style={{
|
||||
marginTop: 14,
|
||||
fontSize: 18,
|
||||
fontWeight: 500,
|
||||
color: w.latest ? c.ink : c.faint,
|
||||
}}
|
||||
>
|
||||
{w.label}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* footer */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 22,
|
||||
paddingTop: 22,
|
||||
borderTop: `1px solid ${c.line}`,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
|
||||
<span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
|
||||
2.56T tokens last week · +482.3B added
|
||||
</div>
|
||||
<div style={{ color: c.ink }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill, Easing, Img, interpolate, staticFile, useCurrentFrame } from "remotion"
|
||||
|
||||
const c = {
|
||||
white: "#ffffff",
|
||||
dim: "rgba(255,255,255,0.74)",
|
||||
}
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
|
||||
// verified: OpenCode Go, week of Jun 22-28, 2026 (2026-W26)
|
||||
// 19,642,742,937,105 tokens / 173,651,197 requests = 113,116 tokens/request
|
||||
const AVG = 113116
|
||||
const K = Math.round(AVG / 1000) // 113
|
||||
|
||||
const nf = new Intl.NumberFormat("en-US")
|
||||
|
||||
function DataWordmark({ height = 30 }: { height?: number }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.white }}>
|
||||
<path opacity="0.35" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function NovelTokens() {
|
||||
const frame = useCurrentFrame()
|
||||
|
||||
const k = Math.round(
|
||||
K *
|
||||
interpolate(frame, [18, 92], [0, 1], {
|
||||
extrapolateLeft: "clamp",
|
||||
extrapolateRight: "clamp",
|
||||
easing: Easing.out(Easing.cubic),
|
||||
}),
|
||||
)
|
||||
|
||||
const zoom = interpolate(frame, [0, 150], [1.06, 1.12], {
|
||||
extrapolateRight: "clamp",
|
||||
easing: Easing.inOut(Easing.quad),
|
||||
})
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: "#0c0c0c", overflow: "hidden" }}>
|
||||
<Img
|
||||
src={staticFile("book.jpg")}
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
objectPosition: "center 34%",
|
||||
transform: `scale(${zoom})`,
|
||||
transformOrigin: "center 30%",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* legibility scrims */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
background:
|
||||
"linear-gradient(to bottom, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0) 20%, rgba(0,0,0,0.1) 44%, rgba(0,0,0,0.86) 100%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
boxSizing: "border-box",
|
||||
padding: 64,
|
||||
color: c.white,
|
||||
fontFamily: MONO,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.dim, letterSpacing: 1 }}>JUN 22–28, 2026</div>
|
||||
</div>
|
||||
|
||||
{/* bottom block */}
|
||||
<div>
|
||||
<div style={{ fontSize: 23, fontWeight: 600, color: c.dim, letterSpacing: 2, marginBottom: 8 }}>
|
||||
OPENCODE GO · LAST WEEK
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 168,
|
||||
fontWeight: 600,
|
||||
lineHeight: 0.92,
|
||||
letterSpacing: -5,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
{k}K
|
||||
</div>
|
||||
<div style={{ fontSize: 50, fontWeight: 600, letterSpacing: -1, marginTop: 4 }}>tokens per request</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 30,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ color: c.dim }}>{nf.format(AVG)} tokens / request · last week</div>
|
||||
<div style={{ color: c.white }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill, Easing, Img, interpolate, staticFile, useCurrentFrame } from "remotion"
|
||||
|
||||
const c = {
|
||||
white: "#ffffff",
|
||||
dim: "rgba(255,255,255,0.72)",
|
||||
faint: "rgba(255,255,255,0.55)",
|
||||
}
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
|
||||
// verified: NZ OpenCode Go, week of Jun 22-28, 2026 (2026-W26)
|
||||
const TOKENS = 40_915_594_381 // 40.9B
|
||||
const SHEEP = 23_600_000 // 23.6M
|
||||
const PER_SHEEP = Math.round(TOKENS / SHEEP) // 1,734
|
||||
const nf = new Intl.NumberFormat("en-US")
|
||||
|
||||
// the correct opencode "DATA" wordmark (white, over photo)
|
||||
function DataWordmark({ height = 30 }: { height?: number }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.white }}>
|
||||
<path opacity="0.35" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function NZSheep() {
|
||||
const frame = useCurrentFrame()
|
||||
|
||||
const count = Math.round(
|
||||
PER_SHEEP *
|
||||
interpolate(frame, [18, 90], [0, 1], {
|
||||
extrapolateLeft: "clamp",
|
||||
extrapolateRight: "clamp",
|
||||
easing: Easing.out(Easing.cubic),
|
||||
}),
|
||||
)
|
||||
|
||||
// slow Ken Burns push-in (scale up only — never reveals an edge)
|
||||
const zoom = interpolate(frame, [0, 150], [1.06, 1.12], {
|
||||
extrapolateRight: "clamp",
|
||||
easing: Easing.inOut(Easing.quad),
|
||||
})
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: "#0c0c0c", overflow: "hidden" }}>
|
||||
{/* the sheep, staring */}
|
||||
<Img
|
||||
src={staticFile("sheep.jpg")}
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
objectPosition: "center 38%",
|
||||
transform: `scale(${zoom})`,
|
||||
transformOrigin: "center 35%",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* legibility scrims */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
background:
|
||||
"linear-gradient(to bottom, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 22%, rgba(0,0,0,0) 48%, rgba(0,0,0,0.78) 100%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* content */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
boxSizing: "border-box",
|
||||
padding: 64,
|
||||
color: c.white,
|
||||
fontFamily: MONO,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.dim, letterSpacing: 1 }}>JUN 22–28, 2026</div>
|
||||
</div>
|
||||
|
||||
{/* bottom block */}
|
||||
<div>
|
||||
<div style={{ fontSize: 23, fontWeight: 600, color: c.dim, letterSpacing: 2, marginBottom: 8 }}>
|
||||
OPENCODE GO · NEW ZEALAND
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 168,
|
||||
fontWeight: 600,
|
||||
lineHeight: 0.92,
|
||||
letterSpacing: -5,
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
{nf.format(count)}
|
||||
</div>
|
||||
<div style={{ fontSize: 50, fontWeight: 600, letterSpacing: -1, marginTop: 4 }}>tokens per sheep</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 34,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ color: c.dim }}>40.9B tokens ÷ 23.6M sheep · last week</div>
|
||||
<div style={{ color: c.white }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
import React from "react"
|
||||
import { AbsoluteFill, Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion"
|
||||
import { days, launchIndex, glmWeekTokensT, segments } from "./data"
|
||||
|
||||
// stats.opencode.ai design tokens (light theme)
|
||||
const c = {
|
||||
bg: "#ffffff",
|
||||
ink: "#161616",
|
||||
muted: "#5c5c5c",
|
||||
faint: "#808080",
|
||||
line: "#e6e6e6",
|
||||
dot: "#ededed",
|
||||
accent: "#3b5cf6",
|
||||
accentHi: "#5b78ff",
|
||||
}
|
||||
|
||||
const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
|
||||
const W = 1080
|
||||
|
||||
const DOT_MASK =
|
||||
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
|
||||
|
||||
const field = segments.filter((s) => !s.hero)
|
||||
const glmColor = segments.find((s) => s.hero)!.color
|
||||
|
||||
const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v))
|
||||
|
||||
// the correct opencode "DATA" wordmark (from stats.opencode.ai header)
|
||||
function DataWordmark({ height = 30, color = c.ink }: { height?: number; color?: string }) {
|
||||
return (
|
||||
<svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color }}>
|
||||
<path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
|
||||
<path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
|
||||
<path
|
||||
d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
|
||||
<path
|
||||
d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function GLM52Rise() {
|
||||
const frame = useCurrentFrame()
|
||||
const { fps } = useVideoConfig()
|
||||
|
||||
// ---------- virtual camera ----------
|
||||
// open zoomed-in on the field, pan right while the blue fills, then pull back to reveal.
|
||||
const K = [0, 32, 150, 206, 240]
|
||||
const ease = Easing.inOut(Easing.cubic)
|
||||
const opt = { extrapolateLeft: "clamp" as const, extrapolateRight: "clamp" as const, easing: ease }
|
||||
const s = interpolate(frame, K, [1.82, 1.72, 1.72, 1.0, 1.0], opt)
|
||||
let fx = interpolate(frame, K, [420, 438, 760, 540, 540], opt)
|
||||
let fy = interpolate(frame, K, [664, 664, 664, 540, 540], opt)
|
||||
// keep the framing inside the 1080 canvas so edges never reveal black
|
||||
fx = clamp(fx, 540 / s, W - 540 / s)
|
||||
fy = clamp(fy, 540 / s, W - 540 / s)
|
||||
const camera = `translate(${540 - fx * s}px, ${540 - fy * s}px) scale(${s})`
|
||||
|
||||
// ---------- blue sweep (synced to the pan) ----------
|
||||
const p = interpolate(frame, [32, 150], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: ease })
|
||||
const revealAmount = p * (days.length - launchIndex) + 0.35
|
||||
const fillOf = (i: number) => clamp(revealAmount - (i - launchIndex), 0, 1)
|
||||
|
||||
// token number climbs as the camera pulls back and the headline re-enters frame
|
||||
const tokensT =
|
||||
glmWeekTokensT *
|
||||
interpolate(frame, [150, 202], [0, 1], {
|
||||
extrapolateLeft: "clamp",
|
||||
extrapolateRight: "clamp",
|
||||
easing: Easing.out(Easing.cubic),
|
||||
})
|
||||
|
||||
// chart geometry
|
||||
const chartH = 440
|
||||
const chartW = 936
|
||||
const gap = 14
|
||||
const EXAGGERATE = 2.876 // broken y-axis: GLM-5.2 magnified ~2.9x for emphasis
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: c.bg, overflow: "hidden" }}>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: W,
|
||||
height: W,
|
||||
background: c.bg,
|
||||
transformOrigin: "0 0",
|
||||
transform: camera,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: W,
|
||||
height: W,
|
||||
boxSizing: "border-box",
|
||||
padding: 72,
|
||||
color: c.ink,
|
||||
fontFamily: MONO,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{/* header */}
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<DataWordmark height={30} />
|
||||
<div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 12–25, 2026</div>
|
||||
</div>
|
||||
|
||||
{/* headline (static) */}
|
||||
<div style={{ marginTop: 52 }}>
|
||||
<div style={{ fontSize: 92, fontWeight: 600, lineHeight: 0.98, letterSpacing: -2 }}>
|
||||
GLM-5.2 <span style={{ color: c.accent }}>broke out</span>
|
||||
</div>
|
||||
<div style={{ marginTop: 22, fontSize: 30, fontWeight: 500, color: c.muted }}>
|
||||
From 0 to <span style={{ color: c.ink }}>{tokensT.toFixed(2)}T tokens</span> in a week.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* stacked chart */}
|
||||
<div style={{ flex: 1, display: "flex", alignItems: "flex-end", marginTop: 40 }}>
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
width: chartW,
|
||||
height: chartH,
|
||||
margin: "0 auto",
|
||||
borderBottom: `2px solid ${c.ink}`,
|
||||
boxSizing: "border-box",
|
||||
}}
|
||||
>
|
||||
{/* faint dotted backdrop */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: -8,
|
||||
right: -8,
|
||||
top: -8,
|
||||
bottom: 0,
|
||||
background: c.dot,
|
||||
WebkitMaskImage: DOT_MASK,
|
||||
maskImage: DOT_MASK,
|
||||
WebkitMaskSize: "12px 12px",
|
||||
maskSize: "12px 12px",
|
||||
WebkitMaskRepeat: "repeat",
|
||||
maskRepeat: "repeat",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* columns */}
|
||||
<div style={{ position: "absolute", inset: 0, display: "flex", gap, alignItems: "flex-end" }}>
|
||||
{days.map((d, i) => {
|
||||
const glmShare = d.glm / d.total
|
||||
const blueH = Math.round(glmShare * EXAGGERATE * chartH)
|
||||
const filled = Math.round(blueH * fillOf(i))
|
||||
const slotGap = filled > 2 ? 5 : 0
|
||||
const fieldH = chartH - filled - slotGap
|
||||
const fieldTotal = d.dsf + d.dsp + d.mm + d.others
|
||||
return (
|
||||
<div key={i} style={{ position: "relative", flex: 1, height: chartH }}>
|
||||
{/* gray field of other models (already in place) */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: fieldH,
|
||||
display: "flex",
|
||||
flexDirection: "column-reverse",
|
||||
}}
|
||||
>
|
||||
{field.map((seg) => (
|
||||
<div
|
||||
key={seg.key}
|
||||
style={{
|
||||
height: Math.round(((d[seg.key as keyof typeof d] as number) / fieldTotal) * fieldH),
|
||||
background: seg.color,
|
||||
borderTop: `2px solid ${c.bg}`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{/* GLM-5.2, animates in */}
|
||||
{filled > 2 && (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: filled,
|
||||
background: glmColor,
|
||||
borderTop: `2px solid ${c.accentHi}`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* day axis */}
|
||||
<div style={{ display: "flex", gap, width: chartW, margin: "14px auto 0" }}>
|
||||
{days.map((d, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
flex: 1,
|
||||
textAlign: "center",
|
||||
fontSize: 15,
|
||||
fontWeight: 500,
|
||||
color: i === days.length - 1 ? c.ink : c.faint,
|
||||
}}
|
||||
>
|
||||
{i === 0 || i === launchIndex || i === days.length - 1 ? d.date : ""}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* footer */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 28,
|
||||
paddingTop: 22,
|
||||
borderTop: `1px solid ${c.line}`,
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
|
||||
<span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
|
||||
GLM-5.2
|
||||
</div>
|
||||
<div style={{ color: c.ink }}>opencode.ai/data</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* This file is auto-generated by SST. Do not edit. */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/* deno-fmt-ignore-file */
|
||||
/* biome-ignore-all lint: auto-generated */
|
||||
|
||||
/// <reference path="../../sst-env.d.ts" />
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 62 KiB |
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"packages/ai": {
|
||||
"name": "@opencode/ai",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-providers": "3.1057.0",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -55,7 +55,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -112,7 +112,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode/cli",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode.cjs",
|
||||
"opencode2": "./bin/opencode2.cjs",
|
||||
@@ -179,7 +179,7 @@
|
||||
},
|
||||
"packages/client": {
|
||||
"name": "@opencode/client",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/protocol": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -192,9 +192,10 @@
|
||||
"@typescript/native-preview": "catalog:",
|
||||
"effect": "catalog:",
|
||||
"solid-js": "catalog:",
|
||||
"zod": "catalog:",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"effect": "4.0.0-rc.112",
|
||||
"effect": "4.0.0-rc.118",
|
||||
"solid-js": ">=1.9.0",
|
||||
},
|
||||
"optionalPeers": [
|
||||
@@ -204,7 +205,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode/codemode",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -217,7 +218,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode/console-app",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -253,7 +254,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode/console-core",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -280,7 +281,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode/console-function",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -297,7 +298,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode/console-mail",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -321,7 +322,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode/console-support",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -341,9 +342,10 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode/core",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@ai-sdk/cohere": "3.0.27",
|
||||
"@ai-sdk/gateway": "3.0.104",
|
||||
"@ai-sdk/perplexity": "3.0.26",
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@ai-sdk/provider-utils": "4.0.23",
|
||||
@@ -368,17 +370,20 @@
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
"fuzzysort": "3.1.0",
|
||||
"gitlab-ai-provider": "6.19.0",
|
||||
"gitlab-ai-provider": "6.18.0",
|
||||
"google-auth-library": "10.5.0",
|
||||
"gray-matter": "4.0.3",
|
||||
"htmlparser2": "8.0.2",
|
||||
"http-proxy-agent": "7.0.2",
|
||||
"https-proxy-agent": "7.0.6",
|
||||
"ignore": "7.0.5",
|
||||
"immer": "11.1.4",
|
||||
"jose": "6.0.11",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"mime-types": "3.0.2",
|
||||
"tree-sitter-bash": "0.25.0",
|
||||
"tree-sitter-powershell": "0.25.10",
|
||||
"venice-ai-sdk-provider": "2.1.1",
|
||||
"web-tree-sitter": "0.25.10",
|
||||
"which": "6.0.1",
|
||||
"zod": "catalog:",
|
||||
@@ -402,11 +407,12 @@
|
||||
"@types/node": "catalog:",
|
||||
"@types/which": "3.0.4",
|
||||
"drizzle-kit": "catalog:",
|
||||
"fast-check": "catalog:",
|
||||
},
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode/desktop",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"electron-context-menu": "5.0.0",
|
||||
@@ -451,7 +457,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode/enterprise",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
@@ -488,7 +494,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode/function",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -504,12 +510,8 @@
|
||||
},
|
||||
"packages/gui-extensions": {
|
||||
"name": "@opencode/gui-extensions",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@betteroffice/docx": "0.4.3",
|
||||
"@betteroffice/fonts": "0.4.0",
|
||||
"@betteroffice/pptx": "0.2.0",
|
||||
"@betteroffice/xlsx": "0.3.0",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
"@dnd-kit/dom": "0.5.0",
|
||||
"@dnd-kit/solid": "0.5.0",
|
||||
@@ -553,9 +555,9 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode/http-recorder",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -572,7 +574,7 @@
|
||||
},
|
||||
"packages/httpapi-codegen": {
|
||||
"name": "@opencode/httpapi-codegen",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
"prettier": "3.6.2",
|
||||
@@ -585,7 +587,7 @@
|
||||
},
|
||||
"packages/latex": {
|
||||
"name": "@opencode/latex",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -599,7 +601,7 @@
|
||||
},
|
||||
"packages/merman": {
|
||||
"name": "@opencode/merman",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -614,7 +616,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode/plugin",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode/ai": "workspace:*",
|
||||
@@ -622,7 +624,9 @@
|
||||
"@opencode/protocol": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
"@opencode/util": "workspace:*",
|
||||
"@standard-schema/spec": "catalog:",
|
||||
"effect": "catalog:",
|
||||
"zod": "catalog:",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opencode/theme": "workspace:*",
|
||||
@@ -651,7 +655,7 @@
|
||||
},
|
||||
"packages/plugin-browser": {
|
||||
"name": "@opencode/plugin-browser",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -681,7 +685,7 @@
|
||||
},
|
||||
"packages/protocol": {
|
||||
"name": "@opencode/protocol",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/schema": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -696,7 +700,7 @@
|
||||
},
|
||||
"packages/schema": {
|
||||
"name": "@opencode/schema",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -720,7 +724,7 @@
|
||||
},
|
||||
"packages/sdk": {
|
||||
"name": "@opencode/sdk",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -741,7 +745,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode/server",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"@effect/platform-node-shared": "catalog:",
|
||||
@@ -750,6 +754,7 @@
|
||||
"@opencode/schema": "workspace:*",
|
||||
"@opencode/simulation": "workspace:*",
|
||||
"@opencode/util": "workspace:*",
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -762,7 +767,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode/session-ui",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode/client": "workspace:*",
|
||||
@@ -797,7 +802,7 @@
|
||||
},
|
||||
"packages/simulation": {
|
||||
"name": "@opencode/simulation",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/ai": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -817,7 +822,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode/stats-app",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -851,7 +856,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode/stats-core",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -870,7 +875,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode/stats-server",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -916,7 +921,7 @@
|
||||
},
|
||||
"packages/theme": {
|
||||
"name": "@opencode/theme",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opentui/core": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -930,7 +935,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode/tui",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -964,7 +969,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode/ui",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -973,7 +978,6 @@
|
||||
"fuzzysort": "catalog:",
|
||||
"katex": "0.16.47",
|
||||
"marked": "catalog:",
|
||||
"marked-katex-extension": "5.1.13",
|
||||
"marked-shiki": "catalog:",
|
||||
"motion": "12.34.5",
|
||||
"remeda": "catalog:",
|
||||
@@ -1000,7 +1004,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode/util",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@effect/opentelemetry": "catalog:",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -1038,7 +1042,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode/web",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -1079,7 +1083,7 @@
|
||||
},
|
||||
"services/update": {
|
||||
"name": "@opencode/update",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"dependencies": {
|
||||
"jose": "6.0.11",
|
||||
"semver": "catalog:",
|
||||
@@ -1145,10 +1149,10 @@
|
||||
"catalog": {
|
||||
"@cloudflare/workers-types": "4.20251008.0",
|
||||
"@corvu/drawer": "0.2.4",
|
||||
"@effect/opentelemetry": "4.0.0-rc.112",
|
||||
"@effect/platform-node": "4.0.0-rc.112",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
|
||||
"@effect/opentelemetry": "4.0.0-rc.118",
|
||||
"@effect/platform-node": "4.0.0-rc.118",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.118",
|
||||
"@hono/standard-validator": "0.2.0",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"@kobalte/core": "0.13.13",
|
||||
@@ -1188,7 +1192,8 @@
|
||||
"dompurify": "3.4.14",
|
||||
"drizzle-kit": "1.0.0-rc.5-ab785fc",
|
||||
"drizzle-orm": "1.0.0-rc.5-169397b",
|
||||
"effect": "4.0.0-rc.112",
|
||||
"effect": "4.0.0-rc.118",
|
||||
"fast-check": "4.9.0",
|
||||
"fuzzysort": "3.1.0",
|
||||
"get-east-asian-width": "1.6.0",
|
||||
"hono": "4.10.7",
|
||||
@@ -1232,6 +1237,8 @@
|
||||
|
||||
"@ai-sdk/cohere": ["@ai-sdk/cohere@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OqcCq2PiFY1dbK/0Ck45KuvE8jfdxRuuAE9Y5w46dAk6U+9vPOeg1CDcmR+ncqmrYrhRl3nmyDttyDahyjCzAw=="],
|
||||
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="],
|
||||
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="],
|
||||
|
||||
"@ai-sdk/perplexity": ["@ai-sdk/perplexity@3.0.26", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-dXzrVsLR5f6tr+U04jq4AXoRroGFBTvODnLgss0SWbzNjGGQg3XqtQ9j7rCLo6o8qbYGuAHvqUrIpUCuiscuFg=="],
|
||||
@@ -1638,14 +1645,6 @@
|
||||
|
||||
"@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="],
|
||||
|
||||
"@betteroffice/docx": ["@betteroffice/docx@0.4.3", "", { "peerDependencies": { "@betteroffice/fonts": "^0" }, "optionalPeers": ["@betteroffice/fonts"] }, "sha512-CEErXJH3iCsi2a61gTNkAofLCzSTcktLmp710gGhMwbBfOqwQ2yI7dRFBV3ElGa9JxkS03IfejvLX0sAvlTrUQ=="],
|
||||
|
||||
"@betteroffice/fonts": ["@betteroffice/fonts@0.4.0", "", { "peerDependencies": { "@betteroffice/fonts-cjk": "^0" }, "optionalPeers": ["@betteroffice/fonts-cjk"] }, "sha512-x1BVwYDAgY5R6TWI4t9NLguSiAEbH5GItN2ZlpBIFoRXTIJgjBsXd6sUxPGpexXOyY6KdhRjG8XvHjyAYxEGCw=="],
|
||||
|
||||
"@betteroffice/pptx": ["@betteroffice/pptx@0.2.0", "", {}, "sha512-pNPQ58tlA+pVibERbLdQNskvP7a0GIMf4jhkCU/gPp8043Ichf6gB3PSb4ra9sfqoIaWqOaZKCWyptovA2+Q0A=="],
|
||||
|
||||
"@betteroffice/xlsx": ["@betteroffice/xlsx@0.3.0", "", {}, "sha512-K2bHtdk/epAxsmvxJlIWBRndjP3ltQU0Oh3p4gcZd2n5/YgXglo3SmMYX4nQe8WEm/yvz91p+aIasKyXXQP9Wg=="],
|
||||
|
||||
"@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
|
||||
|
||||
"@brendonovich/vite-plugin-opencode": ["@brendonovich/vite-plugin-opencode@0.1.3", "", { "dependencies": { "@babel/core": "^7.29.0", "@opencode-ai/client": "0.0.0-beta-18050" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-iiIwlNoycOMUiaUzL1ZirLapCG3WY8cg9hSj4KgE/JYIWgqauoHikIlfUt7SdMqqGIkb4iZu6I1MxgDDJaRfBA=="],
|
||||
@@ -1726,13 +1725,13 @@
|
||||
|
||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.12.0", "", {}, "sha512-mlUE+rZ8CatQekLhnaiN91Iemdd+e2gFKooGlnRB3oPTL3VghLfX24dx7HrzMNeC1JrIB/0kpsfyty3f5HNfxQ=="],
|
||||
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.112", "", { "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-rc.112" }, "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-OTRv1DxTHUmnakgJ6XVM8wVgF1KgZH4UXnOemwSLUwUjXO+RCikzF8oR/rlVmOGq81KtQzj1URM4M4nchlQOuQ=="],
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.118", "", { "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-rc.118" }, "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-N5dvEeCj1W/9zgBvyyp/GucOKOEJdV7QNirWp+4g/axFKTB/cfV2gx/ZhMDUb69HzlyRmOelNvKEmB3RA0PdVw=="],
|
||||
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.112", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.112", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.112", "redis": ">=5.0.0 <7.0.0" } }, "sha512-/BMAcdNGQQskLmI0Zoa95KfTZkr9HV9N4NSxaSrusG6GeW6Ulp9KvZ+Rlaiw8lnOt43CXjFLdfll5/k5rxL4hQ=="],
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.118", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.118", "undici": "^8.11.2" }, "peerDependencies": { "effect": "^4.0.0-rc.118", "redis": ">=5.0.0 <7.0.0" } }, "sha512-qdAxPZ+5bKxVnzkwziqcHZTHRHz2hyfFX6NhwEmm75CBpmaIzXIZR2LRqGd1/8eI3J3cOrXcAYzByhln7T1/EA=="],
|
||||
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.112", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ=="],
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.118", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.22.0" }, "peerDependencies": { "effect": "^4.0.0-rc.118" } }, "sha512-pNbmIlxbAUxAthUNsp2xm1NLG9kxoYecsPkoYl9mNF2oxPcKDxAvkOar7tYnLSUpXJeATm4pxYVipdZjQfqO4Q=="],
|
||||
|
||||
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.112", "", { "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-EqR8pWZo3VzedRvP6qo5HcfqNmFvSa+sQLWQl3oBMx2KY1FCc8NYjep79wYjNkW0qABnffrPUXCMTOncd1A+5g=="],
|
||||
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.118", "", { "peerDependencies": { "effect": "^4.0.0-rc.118" } }, "sha512-UF0oVOK7mQvEwpxySR9VTk5YoP5luRI//Z8NMOJKVG/SbZbsORGACd7Np+KZRiXXjgzSXEpfGb7Gs3G1cKfUCg=="],
|
||||
|
||||
"@electron-internal/extract-zip": ["@electron-internal/extract-zip@1.0.5", "", {}, "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA=="],
|
||||
|
||||
@@ -2066,18 +2065,6 @@
|
||||
|
||||
"@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="],
|
||||
|
||||
"@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="],
|
||||
|
||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q=="],
|
||||
@@ -3292,6 +3279,8 @@
|
||||
|
||||
"@upstash/redis": ["@upstash/redis@1.38.0", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-wu+dZBptlLy0+MCUEoHmzrY/TnmgDey3+c7EbIGwrLqAvkP8yi5MWZHYGIFtAygmL4Bkz2TdFu+eU0vFPncIcg=="],
|
||||
|
||||
"@vercel/oidc": ["@vercel/oidc@3.2.0", "", {}, "sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug=="],
|
||||
|
||||
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
|
||||
|
||||
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
||||
@@ -3328,6 +3317,8 @@
|
||||
|
||||
"@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="],
|
||||
|
||||
"@workflow/serde": ["@workflow/serde@4.1.0", "", {}, "sha512-pav4F2BoirECWR7Nf1TKt+2eETcBj7jj4cBefQ8VXQCA6NPkaKeLfj/zMgi+3zYV5ZIBT4GuUiphsj0/b9hPQQ=="],
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.14", "", {}, "sha512-T4EDRUBVZYRldYApjEJiU0e1stYWaRAX7CuSnKzrpwdZKo53zGV8/pqfzV6FfwNl9YThD2OumQYvqtvjvgG7aQ=="],
|
||||
|
||||
"@yuuang/ffi-rs-android-arm64": ["@yuuang/ffi-rs-android-arm64@1.3.7", "", { "os": "android", "cpu": "arm64" }, "sha512-t6Wx3Xll6c07Nuk0k3xnZsxKFxlshm92i0U/BiTHc6kQbvu+fMJF+gKsj4yEj886jH51CM3EqZT9Xdhq9CdUVw=="],
|
||||
@@ -3368,6 +3359,8 @@
|
||||
|
||||
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||
|
||||
"ai": ["ai@7.0.66", "", { "dependencies": { "@ai-sdk/gateway": "4.0.52", "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wBUyoCYF3GVr+62nelBgR8YbpTSsMZrzFyOOjiwijylNSM2TFCW35C+Pml2vc59/WLMpyhS/LWZ55M+B9DAcSg=="],
|
||||
|
||||
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
||||
|
||||
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
|
||||
@@ -3910,7 +3903,7 @@
|
||||
|
||||
"editorconfig": ["editorconfig@1.0.7", "", { "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", "minimatch": "^9.0.1", "semver": "^7.5.3" }, "bin": { "editorconfig": "bin/editorconfig" } }, "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw=="],
|
||||
|
||||
"effect": ["effect@4.0.0-rc.112", "", { "dependencies": { "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A=="],
|
||||
"effect": ["effect@4.0.0-rc.118", "", {}, "sha512-hxhpCd+swzrtu9lnyPpEFre2ODQzJ9qxgyL1oHIEY8NKnW4PxTbM1XzplMZXiAsLD62HO+KJc41Nqxr9T791ZQ=="],
|
||||
|
||||
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
||||
|
||||
@@ -4160,7 +4153,7 @@
|
||||
|
||||
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
|
||||
|
||||
"gitlab-ai-provider": ["gitlab-ai-provider@6.19.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-ym+p6PxKvCKfBE3VKYTiacJwsmgq/DrOuGctpBnbIBekdnZT31RM6yTTNdzVS83K3+Ym4M+qNY34HEcTVM6EEQ=="],
|
||||
"gitlab-ai-provider": ["gitlab-ai-provider@6.18.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-dXTXkNt1SFCL7jGlqazHL6iUJEug21qq0tx2s+Tui7jWNUqIAHEzY9WY1+PnZlhxvB56jPPBcFAT0attpjnopg=="],
|
||||
|
||||
"glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
|
||||
|
||||
@@ -4306,7 +4299,7 @@
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="],
|
||||
|
||||
@@ -4620,8 +4613,6 @@
|
||||
|
||||
"marked": ["marked@18.0.11", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw=="],
|
||||
|
||||
"marked-katex-extension": ["marked-katex-extension@5.1.13", "", { "peerDependencies": { "katex": ">=0.16 <0.19", "marked": ">=4 <19" } }, "sha512-+6gVygGg5at9g+YsuIQZk7XcAc6Pg1P0grEJKEWvF7DAwceZ7ZIvU0fhQe6auUqSbnPmSjJxZuICdSCdbGaFRw=="],
|
||||
|
||||
"marked-shiki": ["marked-shiki@1.2.1", "", { "peerDependencies": { "marked": ">=7.0.0", "shiki": ">=1.0.0" } }, "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ=="],
|
||||
|
||||
"marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="],
|
||||
@@ -4750,7 +4741,7 @@
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
|
||||
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
|
||||
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
@@ -4798,10 +4789,6 @@
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="],
|
||||
|
||||
"msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="],
|
||||
|
||||
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
|
||||
|
||||
"mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="],
|
||||
@@ -4844,8 +4831,6 @@
|
||||
|
||||
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
|
||||
|
||||
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
|
||||
|
||||
"node-html-parser": ["node-html-parser@7.1.0", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ=="],
|
||||
|
||||
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
||||
@@ -5642,7 +5627,7 @@
|
||||
|
||||
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
||||
|
||||
"undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
|
||||
"undici": ["undici@8.11.2", "", {}, "sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
@@ -5722,6 +5707,8 @@
|
||||
|
||||
"validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
|
||||
|
||||
"venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.1.1", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.51", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.30" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-w3OHkuzzKZ3r2TOxER6myBYzZJNoDqol+DUHu3NnfBN/GETnUVxecZJab0CHQQ8GZc0jjzpFymepjcLDPS4SQg=="],
|
||||
|
||||
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
||||
|
||||
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
|
||||
@@ -6092,15 +6079,13 @@
|
||||
|
||||
"@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="],
|
||||
|
||||
"@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
|
||||
"@cloudflare/vite-plugin/vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="],
|
||||
|
||||
"@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
|
||||
|
||||
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||
|
||||
"@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=="],
|
||||
"@effect/platform-node-shared/ws": ["ws@8.22.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg=="],
|
||||
|
||||
"@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
||||
|
||||
@@ -6390,6 +6375,12 @@
|
||||
|
||||
"@vscode/emmet-helper/jsonc-parser": ["jsonc-parser@2.3.1", "", {}, "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="],
|
||||
|
||||
"ai/@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.52", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SXUM8jzzuTUJRq+EOgPd5to6DSx0EKslVn+IVZHbUEX6k/3vCPNrvjckbK26HnNxHU/STxm+zTSJteqrO+7Z0w=="],
|
||||
|
||||
"ai/@ai-sdk/provider": ["@ai-sdk/provider@4.0.7", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6or44XprPzKbr8zkmzosowSE0pxkvJcoojBL+mCZvPUt3kvXp3XSNqeVun9golb1acEfSo6yaEBRT18h2VU+1Q=="],
|
||||
|
||||
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@5.0.27", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@standard-schema/spec": "^1.1.0", "@workflow/serde": "4.1.0", "eventsource-parser": "^3.0.8", "undici": "^7.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EzAn4pdgG5g0xXtH6lE2zyNmfjDQIDjATkfqzuidEI35g++hh4+07vnjzkT/RmGmIClPZiRj/Q2GMPV2V7mkHw=="],
|
||||
|
||||
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||
@@ -6526,6 +6517,8 @@
|
||||
|
||||
"gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
|
||||
"globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
|
||||
|
||||
"html-minifier-terser/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="],
|
||||
@@ -6684,6 +6677,8 @@
|
||||
|
||||
"tw-to-css/tailwindcss": ["tailwindcss@3.3.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.18.2", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w=="],
|
||||
|
||||
"unifont/undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
|
||||
|
||||
"unplugin/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
|
||||
"unused-filename/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
@@ -6692,6 +6687,12 @@
|
||||
|
||||
"unzipper/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.69", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@ai-sdk/provider-utils": "4.0.46" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-C99M0T0SpRkcCClmJxbQkpSqGmxLfh3NhTsNF3aNaUQZZ7oXN5sPWi9LGs49X5Q/r9FWxBYeZARXs15xxtGIig=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.40", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw=="],
|
||||
|
||||
"vite-plugin-dynamic-import/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
|
||||
"vite-plugin-icons-spritesheet/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
@@ -7240,6 +7241,8 @@
|
||||
|
||||
"@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
|
||||
|
||||
"ai/@ai-sdk/provider-utils/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||
|
||||
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
@@ -7538,6 +7541,10 @@
|
||||
|
||||
"tw-to-css/tailwindcss/postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.15", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-XeZW1CcDF2GMbH4wejW6xBRI2QCOgnkVYUnxoeDadB1mf85riL2bMUeDoh+6gJ/r4mjNfzUPW8OjLjvwTP0u1Q=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.46", "", { "dependencies": { "@ai-sdk/provider": "3.0.15", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8", "undici": "^6.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tEtld97plCFiYevsJuOkGkeuhQndeMWFBVrJS4AjnbD5AqrNSXRCe0p+BZ3Cju/sxDeeZ9ym3q9YUV8fASA7aQ=="],
|
||||
|
||||
"vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
|
||||
|
||||
"vscode-languageserver/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
|
||||
@@ -8416,6 +8423,8 @@
|
||||
|
||||
"tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider-utils/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||
|
||||
"yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"@astrojs/cloudflare/@cloudflare/vite-plugin/miniflare/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-vzF5I8/QHutYM6j0R73ghqBCRntL6/fegzivyDTO9Ro=",
|
||||
"aarch64-linux": "sha256-foy1hI+cewpLJvNqTZCCNTqV4tnQSDK55ZRs87MvnI8=",
|
||||
"aarch64-darwin": "sha256-wl6+Omz25VxLRMsh0rvFZCqBErk0o3mh9cjuUYsYAP4="
|
||||
"x86_64-linux": "sha256-2RlbJRTEKSliuUbAE2lAktX63JFR/RKAuLkcCou8wb4=",
|
||||
"aarch64-linux": "sha256-P7DAE018lTJNGmttg87U9oaTAuw/wHlnMStdnXYKCr0=",
|
||||
"aarch64-darwin": "sha256-N+NfV1ObOTnW+ez7As+CS+6ci/iRGCQ6cslvyQFCp6E="
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "opencode",
|
||||
"description": "AI-powered development tool",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "bun@1.4.2",
|
||||
@@ -43,10 +43,10 @@
|
||||
"packages/stats/*"
|
||||
],
|
||||
"catalog": {
|
||||
"@effect/opentelemetry": "4.0.0-rc.112",
|
||||
"@effect/platform-node": "4.0.0-rc.112",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
|
||||
"@effect/opentelemetry": "4.0.0-rc.118",
|
||||
"@effect/platform-node": "4.0.0-rc.118",
|
||||
"@effect/platform-node-shared": "4.0.0-rc.118",
|
||||
"@effect/sql-sqlite-bun": "4.0.0-rc.118",
|
||||
"@npmcli/arborist": "9.4.0",
|
||||
"@types/bun": "1.4.0",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
@@ -80,7 +80,8 @@
|
||||
"dompurify": "3.4.14",
|
||||
"drizzle-kit": "1.0.0-rc.5-ab785fc",
|
||||
"drizzle-orm": "1.0.0-rc.5-169397b",
|
||||
"effect": "4.0.0-rc.112",
|
||||
"effect": "4.0.0-rc.118",
|
||||
"fast-check": "4.9.0",
|
||||
"ai": "6.0.168",
|
||||
"cross-spawn": "7.0.6",
|
||||
"hono": "4.10.7",
|
||||
|
||||
@@ -106,41 +106,6 @@ for await (const event of ai.llm.stream(ai.llm.request(input))) {
|
||||
await ai.dispose()
|
||||
```
|
||||
|
||||
## Venice AI
|
||||
|
||||
`Venice` provides native Chat Completions with streaming tools and reasoning. `model` and `chat`
|
||||
select the same API; credentials default to `VENICE_API_KEY`.
|
||||
|
||||
```ts
|
||||
import { LLM } from "@opencode/ai"
|
||||
import { Venice } from "@opencode/ai/providers"
|
||||
import { Effect } from "effect"
|
||||
|
||||
const program = Effect.gen(function* () {
|
||||
const response = yield* LLM.generate({
|
||||
model: Venice.configure({ apiKey: process.env.VENICE_API_KEY }).chat("qwen3-6-27b"),
|
||||
prompt: "Explain this design.",
|
||||
providerOptions: {
|
||||
reasoningEffort: "high",
|
||||
veniceParameters: { includeVeniceSystemPrompt: false },
|
||||
},
|
||||
})
|
||||
console.log(response.text)
|
||||
})
|
||||
```
|
||||
|
||||
Effort lowers to `reasoning.effort`; `reasoning.enabled` and `reasoning.summary` are also available.
|
||||
Supported effort levels and toggles depend on the selected model. Omitted controls preserve its defaults.
|
||||
Venice's added system prompt is disabled by default, matching the previous OpenCode Venice SDK behavior.
|
||||
|
||||
Replay complete `response.message` values to retain signed/encrypted reasoning and Gemini thought
|
||||
signatures, including per-tool signatures. Venice's encrypted scalar trailers are excluded from visible
|
||||
reasoning but retained in provider metadata for replay. Cache affinity uses `promptCacheKey`, and cache-write
|
||||
usage reads Venice's `cache_creation_input_tokens` field.
|
||||
|
||||
The native package entrypoint is `@opencode/ai/providers/venice`. Image generation, embeddings, Responses, and
|
||||
client-side E2EE are not implemented by this provider.
|
||||
|
||||
## Experimental evaluation
|
||||
|
||||
Evaluation models compare shared state with typed choice, score, and boolean questions. The API is
|
||||
@@ -1283,7 +1248,7 @@ const gateway = CloudflareAIGateway.configure({
|
||||
}).model("workers-ai/@cf/meta/llama-3.1-8b-instruct")
|
||||
```
|
||||
|
||||
Included LLM providers: OpenAI, Anthropic, Google (Gemini), Google Vertex, Amazon Bedrock, Azure OpenAI, Baseten, Cerebras, Cohere, Cloudflare AI Gateway, Cloudflare Workers AI, DeepInfra, DeepSeek, Fireworks, Groq, Mistral, OpenRouter, TogetherAI, Vercel AI Gateway, and xAI. Z.ai currently exposes image generation. Generic Chat Completions, Responses, and Anthropic Messages-compatible entrypoints support custom endpoints.
|
||||
Included LLM providers: OpenAI, Anthropic, Google (Gemini), Google Vertex, Amazon Bedrock, Azure OpenAI, Baseten, Cerebras, Cohere, Cloudflare AI Gateway, Cloudflare Workers AI, DeepInfra, DeepSeek, Fireworks, Groq, Mistral, OpenRouter, TogetherAI, and xAI. Z.ai currently exposes image generation. Generic Chat Completions, Responses, and Anthropic Messages-compatible entrypoints support custom endpoints.
|
||||
|
||||
Each named provider owns its module, endpoint, authentication, and route setup. Providers with the same wire format compose the shared protocol directly:
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { OpenAI } from "@opencode/ai/providers"
|
||||
* hover imports and local values to see how the public API is typed.
|
||||
*/
|
||||
|
||||
const apiKey = Config.redacted("OPENAI_API_KEY")
|
||||
const apiKey = Config.Redacted("OPENAI_API_KEY")
|
||||
|
||||
// 1. Configure a provider. The configured facade records provider identity,
|
||||
// deployment options, authentication, and defaults. Per-modality selectors pick
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.24",
|
||||
"version": "2.0.22",
|
||||
"name": "@opencode/ai",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as path from "node:path"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { AwsV4Signer } from "aws4fetch"
|
||||
import { Config, ConfigProvider, Effect, FileSystem, PlatformError, Redacted } from "effect"
|
||||
import { FetchHttpClient, HttpClient, HttpClientRequest, type HttpClientResponse } from "effect/unstable/http"
|
||||
import { FetchHttpClient, HttpClient, HttpClientRequest, type HttpClientResponse } from "effect/http"
|
||||
import * as ProviderShared from "../src/protocols/shared"
|
||||
import { CloudflareAIGateway } from "../src/providers/cloudflare-ai-gateway.js"
|
||||
import { CloudflareWorkersAI } from "../src/providers/cloudflare-workers-ai.js"
|
||||
@@ -383,7 +383,7 @@ const readEnvFile = Effect.fn("RecordingEnv.readFile")(function* () {
|
||||
})
|
||||
|
||||
const readConfigString = (provider: ConfigProvider.ConfigProvider, name: string) =>
|
||||
Config.string(name)
|
||||
Config.String(name)
|
||||
.parse(provider)
|
||||
.pipe(
|
||||
Effect.match({
|
||||
|
||||
@@ -42,28 +42,26 @@ const RESPECTS_INLINE_HINTS = new Set([
|
||||
"alibaba-messages",
|
||||
"anthropic-messages",
|
||||
"anthropic-compatible-messages",
|
||||
"bedrock-mantle-messages",
|
||||
"cloudflare-ai-gateway-messages",
|
||||
"google-vertex-messages",
|
||||
"meta-messages",
|
||||
"minimax-messages",
|
||||
"moonshot-messages",
|
||||
"vercel-ai-gateway-messages",
|
||||
"zai-coding-messages",
|
||||
"bedrock-converse",
|
||||
"openrouter",
|
||||
"digitalocean",
|
||||
])
|
||||
|
||||
// OpenRouter and Vercel AI Gateway upstreams other than Anthropic and Alibaba Qwen cache without breakpoints.
|
||||
// Gemini uses only the last breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs
|
||||
// more than none. Qwen ignores breakpoints on tool definitions and caches tools with the system prompt.
|
||||
// OpenRouter upstreams other than Anthropic and Alibaba Qwen cache without breakpoints. Gemini uses only the last
|
||||
// breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs more than none. Qwen ignores
|
||||
// breakpoints on tool definitions and caches tools with the system prompt.
|
||||
const QWEN: CachePolicyObject = { system: true, messages: { tail: 1 } }
|
||||
const gatewayPolicy = (modelID: string): CachePolicyObject => {
|
||||
const openRouterPolicy = (modelID: string): CachePolicyObject => {
|
||||
// `~anthropic/claude-sonnet-latest` style IDs are OpenRouter aliases for the latest model in a family.
|
||||
const id = modelID.replace(/^~/, "")
|
||||
if (id.startsWith("anthropic/")) return AUTO
|
||||
if (id.startsWith("qwen/") || id.startsWith("alibaba/qwen")) return QWEN
|
||||
if (id.startsWith("qwen/")) return QWEN
|
||||
return NONE
|
||||
}
|
||||
|
||||
@@ -171,13 +169,11 @@ const countHints = (request: LLMRequest) =>
|
||||
)
|
||||
|
||||
export const applyCachePolicy = (request: LLMRequest): LLMRequest => {
|
||||
const route = request.model.route.id
|
||||
if (!RESPECTS_INLINE_HINTS.has(route)) return request
|
||||
if (!RESPECTS_INLINE_HINTS.has(request.model.route.id)) return request
|
||||
const policy =
|
||||
(route === "openrouter" || route === "vercel-ai-gateway-messages") &&
|
||||
(request.cache === undefined || request.cache === "auto")
|
||||
? gatewayPolicy(request.model.id)
|
||||
: route === "alibaba-chat" && (request.cache === undefined || request.cache === "auto")
|
||||
request.model.route.id === "openrouter" && (request.cache === undefined || request.cache === "auto")
|
||||
? openRouterPolicy(request.model.id)
|
||||
: request.model.route.id === "alibaba-chat" && (request.cache === undefined || request.cache === "auto")
|
||||
? request.model.id.toLowerCase().startsWith("qwen")
|
||||
? QWEN
|
||||
: NONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import {
|
||||
ChoiceQuestion,
|
||||
EvaluationInput,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export * as Media from "./media.js"
|
||||
|
||||
import { Effect, Encoding, FileSystem, Schema, SchemaGetter } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { Effect, FileSystem, Schema, SchemaGetter } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { HttpClientRequest } from "effect/http"
|
||||
import { ProviderID } from "./schema/ids.js"
|
||||
import { AIError, HttpContext, InvalidProviderOutputError, InvalidRequestError } from "./schema/errors.js"
|
||||
import { ProviderMetadata } from "./schema/options.js"
|
||||
@@ -140,7 +141,7 @@ export class Asset {
|
||||
inline(): Inline | undefined {
|
||||
const source = this.source
|
||||
if (source.type !== "bytes" && source.type !== "base64") return undefined
|
||||
const base64 = source.type === "base64" ? source.data : (this.#base64 ??= Encoding.encodeBase64(source.data))
|
||||
const base64 = source.type === "base64" ? source.data : (this.#base64 ??= Base64.encode(source.data))
|
||||
const mime = this.mediaType.toLowerCase()
|
||||
return { mime, base64, dataUrl: `data:${mime};base64,${base64}` }
|
||||
}
|
||||
@@ -155,7 +156,7 @@ export class Asset {
|
||||
return Effect.fail(invalid(`Cannot materialize provider ref ${source.provider}:${source.id}`))
|
||||
const decoded =
|
||||
source.type === "base64"
|
||||
? Effect.fromResult(Encoding.decodeBase64(source.data)).pipe(
|
||||
? Effect.fromResult(Base64.decode(source.data)).pipe(
|
||||
Effect.mapError((cause) => invalid(`Media asset contains invalid base64 data`, cause)),
|
||||
)
|
||||
: download(source, this.headers)
|
||||
@@ -168,7 +169,7 @@ export class Asset {
|
||||
const source = this.source
|
||||
if (source.type === "base64") return Effect.succeed(source.data)
|
||||
if (this.#base64 !== undefined) return Effect.succeed(this.#base64)
|
||||
return this.bytes().pipe(Effect.map((data) => (this.#base64 = Encoding.encodeBase64(data))))
|
||||
return this.bytes().pipe(Effect.map((data) => (this.#base64 = Base64.encode(data))))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ export class Asset {
|
||||
toJSON() {
|
||||
const source = this.source
|
||||
return {
|
||||
source: source.type === "bytes" ? { ...source, data: Encoding.encodeBase64(source.data) } : source,
|
||||
source: source.type === "bytes" ? { ...source, data: Base64.encode(source.data) } : source,
|
||||
info: this.info,
|
||||
providerMetadata: this.providerMetadata,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Auth } from "../route/auth.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Headers } from "effect/http"
|
||||
import { HttpTransport } from "../route/transport/index.js"
|
||||
import {
|
||||
AIError,
|
||||
@@ -422,74 +422,57 @@ const AnthropicUsage = Schema.StructWithRest(
|
||||
)
|
||||
type AnthropicUsage = Schema.Schema.Type<typeof AnthropicUsage>
|
||||
|
||||
const AnthropicStreamBlock = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
type: Schema.String,
|
||||
id: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
// redacted_thinking blocks arrive whole in content_block_start with the
|
||||
// encrypted payload in `data`; there is no streaming delta sequence.
|
||||
data: Schema.optional(Schema.String),
|
||||
input: Schema.optional(Schema.Unknown),
|
||||
// *_tool_result blocks arrive whole as content_block_start (no streaming
|
||||
// delta) with the structured payload in `content` and the originating
|
||||
// server_tool_use id in `tool_use_id`.
|
||||
tool_use_id: Schema.optional(Schema.String),
|
||||
content: Schema.optional(Schema.Unknown),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
const AnthropicStreamBlock = Schema.Struct({
|
||||
type: Schema.String,
|
||||
id: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
// redacted_thinking blocks arrive whole in content_block_start with the
|
||||
// encrypted payload in `data`; there is no streaming delta sequence.
|
||||
data: Schema.optional(Schema.String),
|
||||
input: Schema.optional(Schema.Unknown),
|
||||
// *_tool_result blocks arrive whole as content_block_start (no streaming
|
||||
// delta) with the structured payload in `content` and the originating
|
||||
// server_tool_use id in `tool_use_id`.
|
||||
tool_use_id: Schema.optional(Schema.String),
|
||||
content: Schema.optional(Schema.Unknown),
|
||||
})
|
||||
type AnthropicStreamBlock = Schema.Schema.Type<typeof AnthropicStreamBlock>
|
||||
const decodeAnthropicStreamBlock = Schema.decodeUnknownOption(AnthropicStreamBlock)
|
||||
|
||||
const AnthropicStreamDelta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
type: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
partial_json: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
stop_reason: optionalNull(Schema.String),
|
||||
stop_sequence: optionalNull(Schema.String),
|
||||
stop_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) }),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
const AnthropicStreamDelta = Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
type: Schema.optional(Schema.String),
|
||||
text: Schema.optional(Schema.String),
|
||||
thinking: Schema.optional(Schema.String),
|
||||
partial_json: Schema.optional(Schema.String),
|
||||
signature: Schema.optional(Schema.String),
|
||||
stop_reason: optionalNull(Schema.String),
|
||||
stop_sequence: optionalNull(Schema.String),
|
||||
stop_details: optionalNull(
|
||||
Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) }),
|
||||
),
|
||||
})
|
||||
type AnthropicStreamDelta = Schema.Schema.Type<typeof AnthropicStreamDelta>
|
||||
const decodeAnthropicStreamDelta = Schema.decodeUnknownOption(AnthropicStreamDelta)
|
||||
|
||||
const AnthropicEvent = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
type: Schema.String,
|
||||
index: Schema.optional(Schema.Number),
|
||||
message: Schema.optional(
|
||||
Schema.StructWithRest(Schema.Struct({ usage: Schema.optional(AnthropicUsage) }), [JsonObject]),
|
||||
),
|
||||
content_block: Schema.optional(Schema.Unknown),
|
||||
delta: Schema.optional(Schema.Unknown),
|
||||
usage: Schema.optional(AnthropicUsage),
|
||||
// `type` and `message` are both required per Anthropic's spec, but
|
||||
// OpenAI-compatible proxies and gateway translations occasionally drop one
|
||||
// or the other; mark them optional so a partial payload still parses and
|
||||
// the parser can fall back to whichever field is populated.
|
||||
error: Schema.optional(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) }),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
const AnthropicEvent = Schema.Struct({
|
||||
type: Schema.String,
|
||||
index: Schema.optional(Schema.Number),
|
||||
message: Schema.optional(Schema.Struct({ usage: Schema.optional(AnthropicUsage) })),
|
||||
content_block: Schema.optional(Schema.Unknown),
|
||||
delta: Schema.optional(Schema.Unknown),
|
||||
usage: Schema.optional(AnthropicUsage),
|
||||
// `type` and `message` are both required per Anthropic's spec, but
|
||||
// OpenAI-compatible proxies and gateway translations occasionally drop one
|
||||
// or the other; mark them optional so a partial payload still parses and
|
||||
// the parser can fall back to whichever field is populated.
|
||||
error: Schema.optional(
|
||||
Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) }),
|
||||
),
|
||||
})
|
||||
type AnthropicEvent = Schema.Schema.Type<typeof AnthropicEvent>
|
||||
|
||||
interface ParserState {
|
||||
@@ -601,7 +584,10 @@ const serverToolResultType = (name: string): AnthropicServerToolResultType | und
|
||||
return undefined
|
||||
}
|
||||
|
||||
const lowerServerToolResult = Effect.fnUntraced(function* (part: ToolResultPart, providerMetadataKey: string) {
|
||||
const lowerServerToolResult = Effect.fn("AnthropicMessages.lowerServerToolResult")(function* (
|
||||
part: ToolResultPart,
|
||||
providerMetadataKey: string,
|
||||
) {
|
||||
const wireType = serverToolResultType(part.name)
|
||||
if (!wireType)
|
||||
return yield* invalid(`Anthropic Messages does not know how to round-trip server tool result for ${part.name}`)
|
||||
@@ -671,7 +657,10 @@ const citationsFromMetadata = (metadata: MediaPart["metadata"]): AnthropicDocume
|
||||
|
||||
const isHttpUrl = (value: string) => /^https?:\/\//i.test(value.trim())
|
||||
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart, breakpoints?: Cache.Breakpoints) {
|
||||
const lowerMedia = Effect.fn("AnthropicMessages.lowerMedia")(function* (
|
||||
part: MediaPart,
|
||||
breakpoints?: Cache.Breakpoints,
|
||||
) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const cacheControlValue = breakpoints ? cacheControl(breakpoints, part.cache) : undefined
|
||||
const fileId = fileIdFromMetadata(part.metadata)
|
||||
@@ -815,6 +804,9 @@ const requireThinkingSignature = (request: LLMRequest) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// Mid-conversation system messages became available with Opus 4.8 and version
|
||||
// 5 of the other supported Claude families. Treat later family versions as
|
||||
// compatible without assuming that every Anthropic Messages model is Claude.
|
||||
// Opus 4.8 and every Claude 5 model accept mid-conversation system messages; later versions inherit support.
|
||||
const supportsNativeSystemUpdates = (request: LLMRequest) => {
|
||||
const version = claudeVersion(String(request.model.id))
|
||||
@@ -823,9 +815,25 @@ const supportsNativeSystemUpdates = (request: LLMRequest) => {
|
||||
return version.major >= 5
|
||||
}
|
||||
|
||||
// Native system messages must follow a user turn (tool results count) or a paused server-tool turn.
|
||||
const acceptsNativeSystemAfter = (message: AnthropicMessage | undefined) =>
|
||||
message?.role === "user" || (message?.role === "assistant" && message.content.at(-1)?.type === "server_tool_use")
|
||||
const endsInServerToolUse = (message: LLMRequest["messages"][number]) => {
|
||||
const last = message.content.at(-1)
|
||||
return message.role === "assistant" && last?.type === "tool-call" && last.providerExecuted === true
|
||||
}
|
||||
|
||||
const canUseNativeSystemUpdate = (request: LLMRequest, index: number) => {
|
||||
const previous = request.messages[index - 1]
|
||||
const next = request.messages[index + 1]
|
||||
// Vertex currently rejects/404s for a system message after local tool results,
|
||||
// so fold it into the user tool-result turn across continuations and history.
|
||||
if (request.model.route.id === "google-vertex-messages" && previous?.role === "tool") return false
|
||||
return (
|
||||
previous !== undefined &&
|
||||
previous.role !== "system" &&
|
||||
(previous.role === "user" || previous.role === "tool" || endsInServerToolUse(previous)) &&
|
||||
next?.role !== "system" &&
|
||||
(next === undefined || next.role === "assistant")
|
||||
)
|
||||
}
|
||||
|
||||
const splitsLocalToolResults = (messages: LLMRequest["messages"], index: number) => {
|
||||
const pending = new Set<string>()
|
||||
@@ -839,7 +847,7 @@ const splitsLocalToolResults = (messages: LLMRequest["messages"], index: number)
|
||||
return pending.size > 0
|
||||
}
|
||||
|
||||
const lowerNativeSystemUpdate = Effect.fnUntraced(function* (
|
||||
const lowerNativeSystemUpdate = Effect.fn("AnthropicMessages.lowerNativeSystemUpdate")(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
breakpoints: Cache.Breakpoints,
|
||||
) {
|
||||
@@ -854,34 +862,12 @@ const lowerNativeSystemUpdate = Effect.fnUntraced(function* (
|
||||
}
|
||||
})
|
||||
|
||||
const lowerWrappedSystemUpdate = Effect.fnUntraced(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
|
||||
request: LLMRequest,
|
||||
breakpoints: Cache.Breakpoints,
|
||||
) {
|
||||
const part = yield* ProviderShared.wrappedSystemUpdate("Anthropic Messages", message)
|
||||
return { type: "text" as const, text: part.text, cache_control: cacheControl(breakpoints, part.cache) }
|
||||
})
|
||||
|
||||
const appendToUserTurn = (messages: AnthropicMessage[], block: AnthropicUserBlock) => {
|
||||
const last = messages.at(-1)
|
||||
if (last?.role === "user") messages[messages.length - 1] = { role: "user", content: [...last.content, block] }
|
||||
else messages.push({ role: "user", content: [block] })
|
||||
}
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, breakpoints: Cache.Breakpoints) {
|
||||
const messages: AnthropicMessage[] = []
|
||||
const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
// Text updates stay where they are unless a user turn follows them; then they move after the latest
|
||||
// user turn, the nearest spot where Anthropic accepts a native system message.
|
||||
const holdUpdates = supportsNativeSystemUpdates(request)
|
||||
const held: Array<LLMRequest["messages"][number]> = []
|
||||
const releaseHeld = Effect.fnUntraced(function* () {
|
||||
const native = acceptsNativeSystemAfter(messages.findLast((message) => message.role !== "system"))
|
||||
for (const update of held.splice(0)) {
|
||||
if (native) messages.push(yield* lowerNativeSystemUpdate(update, breakpoints))
|
||||
else appendToUserTurn(messages, yield* lowerWrappedSystemUpdate(update, breakpoints))
|
||||
}
|
||||
})
|
||||
|
||||
for (const [index, message] of request.messages.entries()) {
|
||||
if (message.role === "system") {
|
||||
@@ -893,8 +879,16 @@ const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, breakpoi
|
||||
}
|
||||
if (splitsLocalToolResults(request.messages, index))
|
||||
return yield* invalid("Anthropic Messages system updates cannot split a local tool call from its tool result")
|
||||
if (holdUpdates) held.push(message)
|
||||
else appendToUserTurn(messages, yield* lowerWrappedSystemUpdate(message, breakpoints))
|
||||
if (supportsNativeSystemUpdates(request) && canUseNativeSystemUpdate(request, index)) {
|
||||
messages.push(yield* lowerNativeSystemUpdate(message, breakpoints))
|
||||
continue
|
||||
}
|
||||
const part = yield* ProviderShared.wrappedSystemUpdate("Anthropic Messages", message)
|
||||
const block = { type: "text" as const, text: part.text, cache_control: cacheControl(breakpoints, part.cache) }
|
||||
const previous = messages.at(-1)
|
||||
if (previous?.role === "user")
|
||||
messages[messages.length - 1] = { role: "user", content: [...previous.content, block] }
|
||||
else messages.push({ role: "user", content: [block] })
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -970,9 +964,7 @@ const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, breakpoi
|
||||
`Anthropic Messages assistant messages only support text, reasoning, and tool-call content for now`,
|
||||
)
|
||||
}
|
||||
if (content.length === 0) continue
|
||||
yield* releaseHeld()
|
||||
messages.push({ role: "assistant", content })
|
||||
if (content.length > 0) messages.push({ role: "assistant", content })
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -993,14 +985,10 @@ const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, breakpoi
|
||||
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] }
|
||||
else messages.push({ role: "user", content })
|
||||
}
|
||||
yield* releaseHeld()
|
||||
|
||||
return messages
|
||||
})
|
||||
|
||||
// TODO: Move per-model capability heuristics (`supportsEffortUpdates`, `supportsNativeSystemUpdates`,
|
||||
// `supportsThinkingBlockBinding`) into explicit model/provider `compatibility` metadata so the protocol
|
||||
// only reads `request.model.compatibility`.
|
||||
// Per-turn effort started with Claude Opus 5 and every Claude 5.1 model; later versions of any family inherit it.
|
||||
const supportsEffortUpdates = (model: LLMRequest["model"]) => {
|
||||
const override = model.compatibility?.supportsEffortUpdates
|
||||
@@ -1312,7 +1300,7 @@ const onContentBlockStart = (
|
||||
return [{ ...state, lifecycle: Lifecycle.stepStart(state.lifecycle, events) }, [...events, result]]
|
||||
}
|
||||
|
||||
const onContentBlockDelta = Effect.fnUntraced(function* (
|
||||
const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(function* (
|
||||
state: ParserState,
|
||||
event: AnthropicEvent & { readonly delta: AnthropicStreamDelta },
|
||||
) {
|
||||
@@ -1380,7 +1368,7 @@ const onContentBlockDelta = Effect.fnUntraced(function* (
|
||||
return [state, NO_EVENTS] satisfies StepResult
|
||||
})
|
||||
|
||||
const onContentBlockStop = Effect.fnUntraced(function* (
|
||||
const onContentBlockStop = Effect.fn("AnthropicMessages.onContentBlockStop")(function* (
|
||||
state: ParserState,
|
||||
event: AnthropicEvent,
|
||||
) {
|
||||
@@ -1451,7 +1439,7 @@ const onMessageDelta = (
|
||||
]
|
||||
}
|
||||
|
||||
const onMessageStop = Effect.fnUntraced(function* (state: ParserState) {
|
||||
const onMessageStop = Effect.fn("AnthropicMessages.onMessageStop")(function* (state: ParserState) {
|
||||
if (Object.keys(state.compactions).length)
|
||||
return yield* ProviderShared.eventError(ADAPTER, "Response ended with an incomplete compaction block")
|
||||
const result = yield* ToolStream.finishAll(ADAPTER, state.tools)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Route } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
@@ -285,7 +286,7 @@ const lowerToolCall = (part: ToolCallPart, normalizeID: (id: string) => string):
|
||||
},
|
||||
})
|
||||
|
||||
const lowerToolResultContent = Effect.fnUntraced(function* (
|
||||
const lowerToolResultContent = Effect.fn("BedrockConverse.lowerToolResultContent")(function* (
|
||||
part: ToolResultPart,
|
||||
documentNames: Set<string>,
|
||||
) {
|
||||
@@ -305,7 +306,7 @@ const lowerToolResultContent = Effect.fnUntraced(function* (
|
||||
return content
|
||||
})
|
||||
|
||||
const lowerToolResult = Effect.fnUntraced(function* (
|
||||
const lowerToolResult = Effect.fn("BedrockConverse.lowerToolResult")(function* (
|
||||
part: ToolResultPart,
|
||||
documentNames: Set<string>,
|
||||
normalizeID: (id: string) => string,
|
||||
@@ -322,7 +323,7 @@ const lowerToolResult = Effect.fnUntraced(function* (
|
||||
// Keep Claude and Nova tool-result images inline; put other models' images beside the result.
|
||||
const keepToolImagesInline = (id: string) => id.includes("anthropic.claude-") || id.includes("amazon.nova-")
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (
|
||||
const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
|
||||
request: LLMRequest,
|
||||
breakpoints: BedrockCache.Breakpoints,
|
||||
) {
|
||||
@@ -610,7 +611,7 @@ interface ParserState {
|
||||
readonly reasoningRedactedContent: Readonly<Record<number, Uint8Array[]>>
|
||||
}
|
||||
|
||||
const encodeRedactedContent = (chunks: ReadonlyArray<Uint8Array>) => Encoding.encodeBase64(concatBytes(chunks))
|
||||
const encodeRedactedContent = (chunks: ReadonlyArray<Uint8Array>) => Base64.encode(concatBytes(chunks))
|
||||
|
||||
const step = (state: ParserState, event: BedrockEvent) =>
|
||||
Effect.gen(function* () {
|
||||
@@ -659,7 +660,7 @@ const step = (state: ParserState, event: BedrockEvent) =>
|
||||
const events: LLMEvent[] = []
|
||||
const redactedChunk = yield* (() => {
|
||||
if (reasoning.redactedContent === undefined) return Effect.succeed(undefined)
|
||||
return Effect.fromResult(Encoding.decodeBase64(reasoning.redactedContent)).pipe(
|
||||
return Effect.fromResult(Base64.decode(reasoning.redactedContent)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
ADAPTER,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EventStreamCodec } from "@smithy/eventstream-codec"
|
||||
import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
|
||||
import { Effect, Encoding, Stream } from "effect"
|
||||
import { Effect, Stream } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { AIError, AIErrorReason, InvalidProviderOutputError } from "../schema/index.js"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import { ProviderShared } from "./shared.js"
|
||||
@@ -47,7 +48,7 @@ const consumeFrames = (route: string) => (state: FrameBufferState, input: FrameI
|
||||
route,
|
||||
classification: "incomplete-stream",
|
||||
message: `Incomplete Bedrock Converse event-stream frame: ${remaining.length} buffered bytes remain at end of stream`,
|
||||
body: Encoding.encodeBase64(remaining),
|
||||
body: Base64.encode(remaining),
|
||||
}),
|
||||
})
|
||||
return [state, []] as const
|
||||
@@ -68,7 +69,7 @@ const consumeFrames = (route: string) => (state: FrameBufferState, input: FrameI
|
||||
`Failed to decode Bedrock Converse event-stream frame: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
Encoding.encodeBase64(view.subarray(0, totalLength)),
|
||||
Base64.encode(view.subarray(0, totalLength)),
|
||||
error,
|
||||
),
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
|
||||
@@ -75,7 +75,7 @@ const usesSse = (request: MediaProtocol.Addressed<Request>) => request.mode ===
|
||||
|
||||
const CONTAINERS: Readonly<Record<string, "raw" | "wav" | "mp3">> = { pcm: "raw", wav: "wav", mp3: "mp3" }
|
||||
|
||||
const outputFormat = Effect.fnUntraced(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const outputFormat = Effect.fn("CartesiaSpeech.outputFormat")(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const sse = usesSse(request)
|
||||
const format = request.format ?? (sse ? "pcm" : "mp3")
|
||||
const container = CONTAINERS[format]
|
||||
@@ -121,7 +121,7 @@ const fromRequest = Effect.fn("CartesiaSpeech.fromRequest")(function* (request:
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fn("CartesiaSpeech.onEvent")(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "chunk" && event.data !== undefined) return SpeechStream.delta(state, event.data)
|
||||
if (event.type === "timestamps" && event.word_timestamps !== undefined) {
|
||||
@@ -140,7 +140,7 @@ const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
return [state, []] as const
|
||||
})
|
||||
|
||||
const finish = Effect.fnUntraced(function* (
|
||||
const finish = Effect.fn("CartesiaSpeech.finish")(function* (
|
||||
state: State,
|
||||
context: MediaProtocol.ResponseContext<Request>,
|
||||
) {
|
||||
|
||||
@@ -252,7 +252,7 @@ const mapUsage = (usage: typeof NativeUsage.Type) =>
|
||||
})
|
||||
|
||||
// Lifecycle deltas open blocks on demand and ends are no-ops for closed blocks, so content-start needs no handling.
|
||||
const step = Effect.fnUntraced(function* (state: State, event: Event) {
|
||||
const step = Effect.fn("CohereChat.step")(function* (state: State, event: Event) {
|
||||
const events: LLMEvent[] = []
|
||||
switch (event.type) {
|
||||
case "message-start":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
import { mergeJsonRecords, type OpenString } from "../schema/index.js"
|
||||
|
||||
@@ -95,7 +95,7 @@ const OUTPUT_FORMATS: Readonly<Record<string, string>> = {
|
||||
}
|
||||
|
||||
/** WAV is served only by the non-streaming endpoints. */
|
||||
const outputFormat = Effect.fnUntraced(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const outputFormat = Effect.fn("ElevenLabsSpeech.outputFormat")(function* (request: MediaProtocol.Addressed<Request>) {
|
||||
const format = request.providerOptions?.outputFormat ?? OUTPUT_FORMATS[request.format ?? "mp3"]
|
||||
if (format === undefined)
|
||||
return yield* route.unsupported(
|
||||
@@ -138,7 +138,7 @@ const path = (request: MediaProtocol.Addressed<Request>) =>
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const onRecord = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const onRecord = Effect.fn("ElevenLabsSpeech.onRecord")(function* (state: State, frame: string) {
|
||||
const record = yield* decodeRecord(frame)
|
||||
const [next, events] = SpeechStream.delta(state, record.audio_base64)
|
||||
const alignment = record.alignment
|
||||
@@ -169,7 +169,7 @@ const describeOutput = (format: string) => {
|
||||
return encoding === undefined ? SpeechStream.container(codec, sampleRate) : SpeechStream.pcm(encoding, sampleRate)
|
||||
}
|
||||
|
||||
const finish = Effect.fnUntraced(function* (
|
||||
const finish = Effect.fn("ElevenLabsSpeech.finish")(function* (
|
||||
state: State,
|
||||
context: MediaProtocol.ResponseContext<Request>,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
import { mergeJsonRecords, type OpenString } from "../schema/index.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -283,7 +283,7 @@ const lowerToolConfig = (toolChoice: NonNullable<LLMRequest["toolChoice"]>) =>
|
||||
tool: (name) => ({ functionCallingConfig: { mode: "ANY" as const, allowedFunctionNames: [name] } }),
|
||||
})
|
||||
|
||||
const lowerContentPart = Effect.fnUntraced(function* (part: TextPart | MediaPart) {
|
||||
const lowerContentPart = Effect.fn("Gemini.lowerContentPart")(function* (part: TextPart | MediaPart) {
|
||||
if (part.type === "text") return { text: part.text }
|
||||
return yield* GeminiGenerateContent.mediaPart("Gemini", part.media)
|
||||
})
|
||||
@@ -302,7 +302,7 @@ const lowerToolCall = (part: ToolCallPart, omitIds: boolean, metadataKey: string
|
||||
thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey),
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request: LLMRequest) {
|
||||
const contents: GeminiContent[] = []
|
||||
const metadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
const omitCallIds = omitsFunctionCallIds(request.model.id)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -182,7 +182,7 @@ type StepResult = readonly [ParserState, ReadonlyArray<LLMEvent>]
|
||||
// =============================================================================
|
||||
// Request Body Construction
|
||||
// =============================================================================
|
||||
const mediaContent = Effect.fnUntraced(function* (asset: Media.Asset) {
|
||||
const mediaContent = Effect.fn("GoogleInteractions.mediaContent")(function* (asset: Media.Asset) {
|
||||
if (
|
||||
asset.kind !== "image" &&
|
||||
asset.kind !== "audio" &&
|
||||
@@ -208,7 +208,7 @@ const signature = (metadata: ProviderMetadata | undefined, key: string) => {
|
||||
: undefined
|
||||
}
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fn("GoogleInteractions.lowerMessages")(function* (request: LLMRequest) {
|
||||
const steps: InputStep[] = []
|
||||
const key = request.model.route.providerMetadataKey ?? String(request.model.provider)
|
||||
for (const message of request.messages) {
|
||||
@@ -275,7 +275,7 @@ const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
return steps
|
||||
})
|
||||
|
||||
const lowerToolResult = Effect.fnUntraced(function* (part: ToolResultPart) {
|
||||
const lowerToolResult = Effect.fn("GoogleInteractions.lowerToolResult")(function* (part: ToolResultPart) {
|
||||
if (part.result.type === "json" && ProviderShared.isRecord(part.result.value)) return part.result.value
|
||||
if (part.result.type !== "content") return ProviderShared.toolResultText(part)
|
||||
|
||||
@@ -364,7 +364,7 @@ const mapUsage = (usage: RawUsage | undefined, key: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
const onStart = Effect.fnUntraced(function* (
|
||||
const onStart = Effect.fn("GoogleInteractions.onStart")(function* (
|
||||
state: ParserState,
|
||||
index: number,
|
||||
step: OutputStep,
|
||||
@@ -402,7 +402,7 @@ const onStart = Effect.fnUntraced(function* (
|
||||
return [{ ...state, lifecycle, tools, steps: { ...state.steps, [index]: step } }, events] satisfies StepResult
|
||||
})
|
||||
|
||||
const onDelta = Effect.fnUntraced(function* (
|
||||
const onDelta = Effect.fn("GoogleInteractions.onDelta")(function* (
|
||||
state: ParserState,
|
||||
index: number,
|
||||
delta: typeof Delta.Type,
|
||||
@@ -447,7 +447,7 @@ const onDelta = Effect.fnUntraced(function* (
|
||||
return yield* ProviderShared.eventError(ADAPTER, `Unsupported Interactions delta: ${delta.type}`, encodeJson(delta))
|
||||
})
|
||||
|
||||
const onStop = Effect.fnUntraced(function* (state: ParserState, index: number) {
|
||||
const onStop = Effect.fn("GoogleInteractions.onStop")(function* (state: ParserState, index: number) {
|
||||
const step = state.steps[index]
|
||||
if (!step) return yield* ProviderShared.eventError(ADAPTER, "Interactions step.stop without step.start")
|
||||
const events: LLMEvent[] = []
|
||||
@@ -465,7 +465,7 @@ const onStop = Effect.fnUntraced(function* (state: ParserState, index: number) {
|
||||
return [{ ...state, tools: result.tools }, result.events ?? []] satisfies StepResult
|
||||
})
|
||||
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, event: Event) {
|
||||
const step = Effect.fn("GoogleInteractions.step")(function* (state: ParserState, event: Event) {
|
||||
switch (event.event_type) {
|
||||
case "step.start":
|
||||
return yield* onStart(state, event.index, event.step)
|
||||
|
||||
@@ -94,7 +94,7 @@ const fromRequest = Effect.fn("GoogleSpeech.fromRequest")(function* (request: Me
|
||||
// 6. Stream parsing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const step = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const step = Effect.fn("GoogleSpeech.step")(function* (state: State, frame: string) {
|
||||
const chunk = yield* decodeChunk(frame)
|
||||
const blocked = GeminiGenerateContent.blocked(route.name, chunk, frame)
|
||||
if (blocked !== undefined) return yield* blocked
|
||||
|
||||
@@ -138,7 +138,7 @@ const turn = (part: Schema.Schema.Type<typeof AudioTranscription>) => {
|
||||
}
|
||||
}
|
||||
|
||||
const step = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const step = Effect.fn("GoogleTranscription.step")(function* (state: State, frame: string) {
|
||||
const chunk = yield* decodeChunk(frame)
|
||||
const blocked = GeminiGenerateContent.blocked(route.name, chunk, frame)
|
||||
if (blocked !== undefined) return yield* blocked
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { LLMEvent, LLMRequest, Message, ToolResultPart } from "../schema/index.js"
|
||||
import { OpenResponses } from "./open-responses.js"
|
||||
@@ -95,7 +96,7 @@ const HOSTED_TOOLS = {
|
||||
image_generation_call: {
|
||||
name: "image_generation",
|
||||
input: () => ({}),
|
||||
result: Effect.fnUntraced(function* (raw: ResponsesHostedTools.Item) {
|
||||
result: Effect.fn("MetaResponses.imageResult")(function* (raw: ResponsesHostedTools.Item) {
|
||||
const item = yield* Schema.decodeUnknownEffect(ImageItem)(raw).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
@@ -113,7 +114,7 @@ const HOSTED_TOOLS = {
|
||||
"Meta returned an image without data",
|
||||
ProviderShared.encodeJson(raw),
|
||||
)
|
||||
const data = yield* Effect.fromResult(Encoding.decodeBase64(item.result)).pipe(
|
||||
const data = yield* Effect.fromResult(Base64.decode(item.result)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(
|
||||
ADAPTER,
|
||||
@@ -136,7 +137,7 @@ const HOSTED_TOOLS = {
|
||||
},
|
||||
} satisfies ResponsesHostedTools.Definitions
|
||||
|
||||
const onEvent = Effect.fnUntraced(function* (
|
||||
const onEvent = Effect.fn("MetaResponses.onEvent")(function* (
|
||||
state: OpenResponses.ParserState,
|
||||
input: OpenResponses.Event,
|
||||
) {
|
||||
@@ -173,7 +174,7 @@ const onEvent = Effect.fnUntraced(function* (
|
||||
] satisfies OpenResponses.StepResult
|
||||
})
|
||||
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, input: OpenResponses.Event) {
|
||||
const step = Effect.fn("MetaResponses.step")(function* (state: ParserState, input: OpenResponses.Event) {
|
||||
const completedItems = new Set(state.completedItems)
|
||||
const event = OpenResponses.normalize(state, input)
|
||||
if (event.type === "response.output_item.done" && event.item && completedItems.has(event.item.id))
|
||||
|
||||
@@ -226,7 +226,7 @@ const MistralEvent = Schema.StructWithRest(
|
||||
type MistralEvent = Schema.Schema.Type<typeof MistralEvent>
|
||||
const MistralStreamEvent = Schema.Union([Schema.Literal(DONE), Protocol.jsonEvent(MistralEvent)])
|
||||
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
const lowerMedia = Effect.fn("MistralChat.lowerMedia")(function* (part: MediaPart) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const url =
|
||||
ProviderShared.mediaUrl(part.media) ??
|
||||
@@ -236,7 +236,7 @@ const lowerMedia = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
return yield* ProviderShared.invalidRequest(`Mistral Chat does not support media type ${part.media.mediaType}`)
|
||||
})
|
||||
|
||||
const lowerUser = Effect.fnUntraced(function* (message: LLMRequest["messages"][number]) {
|
||||
const lowerUser = Effect.fn("MistralChat.lowerUser")(function* (message: LLMRequest["messages"][number]) {
|
||||
const content: MistralUserContent[] = []
|
||||
for (const part of message.content) {
|
||||
if (part.type === "text") {
|
||||
@@ -260,7 +260,7 @@ const lowerToolCall = (part: ToolCallPart, normalizeID: (id: string) => string):
|
||||
function: { name: part.name, arguments: ProviderShared.encodeJson(part.input) },
|
||||
})
|
||||
|
||||
const lowerAssistant = Effect.fnUntraced(function* (
|
||||
const lowerAssistant = Effect.fn("MistralChat.lowerAssistant")(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
normalizeID: (id: string) => string,
|
||||
prefix: boolean,
|
||||
@@ -298,7 +298,7 @@ const lowerAssistant = Effect.fnUntraced(function* (
|
||||
}
|
||||
})
|
||||
|
||||
const lowerToolResults = Effect.fnUntraced(function* (
|
||||
const lowerToolResults = Effect.fn("MistralChat.lowerToolResults")(function* (
|
||||
message: LLMRequest["messages"][number],
|
||||
normalizeID: (id: string) => string,
|
||||
) {
|
||||
@@ -335,7 +335,7 @@ const lowerToolResults = Effect.fnUntraced(function* (
|
||||
return output
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const lowerMessages = Effect.fn("MistralChat.lowerMessages")(function* (request: LLMRequest) {
|
||||
const normalizeID = MistralToolID.normalizer(request)
|
||||
const messages: MistralMessage[] =
|
||||
request.system.length === 0
|
||||
@@ -596,7 +596,7 @@ const toolText = (tool: MistralToolDelta) => {
|
||||
return value === null || value === undefined ? "" : ProviderShared.encodeJson(value)
|
||||
}
|
||||
|
||||
const appendTools = Effect.fnUntraced(function* (
|
||||
const appendTools = Effect.fn("MistralChat.appendTools")(function* (
|
||||
initial: ParserState,
|
||||
events: LLMEvent[],
|
||||
deltas: ReadonlyArray<MistralToolDelta>,
|
||||
@@ -662,7 +662,7 @@ const hasLateContent = (event: MistralEvent) => {
|
||||
)
|
||||
}
|
||||
|
||||
const step = Effect.fnUntraced(function* (state: ParserState, event: MistralEvent) {
|
||||
const step = Effect.fn("MistralChat.step")(function* (state: ParserState, event: MistralEvent) {
|
||||
if (event.error) {
|
||||
const body = ProviderShared.encodeJson(event)
|
||||
return yield* new AIError({
|
||||
@@ -726,7 +726,7 @@ const step = Effect.fnUntraced(function* (state: ParserState, event: MistralEven
|
||||
] as const
|
||||
})
|
||||
|
||||
const finishEvents = Effect.fnUntraced(function* (state: ParserState) {
|
||||
const finishEvents = Effect.fn("MistralChat.finishEvents")(function* (state: ParserState) {
|
||||
if (!state.finishReason)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema, Stream } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Headers } from "effect/http"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import type { HttpContext } from "../schema/index.js"
|
||||
import {
|
||||
|
||||
@@ -301,26 +301,18 @@ export const OpenResponsesBody = Schema.Struct({
|
||||
})
|
||||
export type OpenResponsesBody = Schema.Schema.Type<typeof OpenResponsesBody>
|
||||
|
||||
export const OpenResponsesUsage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
input_tokens: Schema.optional(Schema.Number),
|
||||
input_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
cached_tokens: Schema.optional(Schema.Number),
|
||||
cache_write_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
[JsonObject],
|
||||
),
|
||||
),
|
||||
output_tokens: Schema.optional(Schema.Number),
|
||||
output_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) }), [JsonObject]),
|
||||
),
|
||||
total_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
[JsonObject],
|
||||
)
|
||||
export const OpenResponsesUsage = Schema.Struct({
|
||||
input_tokens: Schema.optional(Schema.Number),
|
||||
input_tokens_details: optionalNull(
|
||||
Schema.Struct({
|
||||
cached_tokens: Schema.optional(Schema.Number),
|
||||
cache_write_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
),
|
||||
output_tokens: Schema.optional(Schema.Number),
|
||||
output_tokens_details: optionalNull(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) })),
|
||||
total_tokens: Schema.optional(Schema.Number),
|
||||
})
|
||||
type OpenResponsesUsage = Schema.Schema.Type<typeof OpenResponsesUsage>
|
||||
|
||||
// The spec requires `id` on every output item, but some gateways drop it from
|
||||
@@ -450,7 +442,7 @@ interface ReasoningStreamItem {
|
||||
// =============================================================================
|
||||
// Request Lowering
|
||||
// =============================================================================
|
||||
export const lowerTool = Effect.fnUntraced(function* (protocolName: string, tool: ToolDefinition) {
|
||||
export const lowerTool = Effect.fn("OpenResponses.lowerTool")(function* (protocolName: string, tool: ToolDefinition) {
|
||||
if (tool.native !== undefined)
|
||||
return yield* ProviderShared.invalidRequest(`${protocolName} does not support provider-native tool ${tool.name}`)
|
||||
return {
|
||||
@@ -507,7 +499,6 @@ const lowerReasoning = (part: ReasoningPart, providerMetadataKey: string): OpenR
|
||||
typeof metadata.reasoningEncryptedContent === "string" || metadata.reasoningEncryptedContent === null
|
||||
? metadata.reasoningEncryptedContent
|
||||
: undefined
|
||||
if (part.text.length === 0 && !encryptedContent) return undefined
|
||||
return {
|
||||
type: "reasoning",
|
||||
...(id === undefined ? {} : { id }),
|
||||
@@ -516,10 +507,7 @@ const lowerReasoning = (part: ReasoningPart, providerMetadataKey: string): OpenR
|
||||
}
|
||||
}
|
||||
|
||||
const decodeImageDetail = ProviderShared.validateWith(Schema.decodeUnknownEffect(OpenResponsesInputImage.fields.detail))
|
||||
const decodeMessageMetadata = ProviderShared.validateWith(Schema.decodeUnknownEffect(MessageMetadata))
|
||||
|
||||
const lowerMedia = Effect.fnUntraced(function* (
|
||||
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (
|
||||
part: MediaPart,
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
@@ -528,8 +516,9 @@ const lowerMedia = Effect.fnUntraced(function* (
|
||||
const media = part.media.inline()
|
||||
const providerMedia = adapter.lowerMedia?.({ part, media, request })
|
||||
if (providerMedia) return providerMedia
|
||||
const rawDetail = part.providerMetadata?.[metadataKey(request.model)]?.detail
|
||||
const detail = rawDetail === undefined ? undefined : yield* decodeImageDetail(rawDetail)
|
||||
const detail = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(OpenResponsesInputImage.fields.detail))(
|
||||
part.providerMetadata?.[metadataKey(request.model)]?.detail,
|
||||
)
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const url = ProviderShared.mediaUrl(part.media)
|
||||
const location = url ?? (yield* ProviderShared.requireInlineMedia(adapter.name, part.media)).dataUrl
|
||||
@@ -602,7 +591,7 @@ const lowerToolResultOutput = Effect.fnUntraced(function* (
|
||||
|
||||
const DEFAULT_EFFORT = "medium"
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (
|
||||
const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
) {
|
||||
@@ -610,8 +599,9 @@ const lowerMessages = Effect.fnUntraced(function* (
|
||||
const providerMetadataKey = metadataKey(request.model)
|
||||
|
||||
for (const message of request.messages) {
|
||||
const rawMetadata = message.providerMetadata?.[providerMetadataKey]
|
||||
const metadata = rawMetadata === undefined ? undefined : yield* decodeMessageMetadata(rawMetadata)
|
||||
const metadata = yield* ProviderShared.validateWith(
|
||||
Schema.decodeUnknownEffect(Schema.UndefinedOr(MessageMetadata)),
|
||||
)(message.providerMetadata?.[providerMetadataKey])
|
||||
if (message.role === "system") {
|
||||
const update = effortUpdate(message)
|
||||
if (update) {
|
||||
@@ -765,7 +755,7 @@ const lowerMessages = Effect.fnUntraced(function* (
|
||||
return input
|
||||
})
|
||||
|
||||
export const lowerConversation = Effect.fnUntraced(function* (
|
||||
export const lowerConversation = Effect.fn("OpenResponses.lowerConversation")(function* (
|
||||
request: LLMRequest,
|
||||
adapter: ProviderAdapter,
|
||||
) {
|
||||
@@ -1152,7 +1142,7 @@ const onReasoningSummaryPartDone = (state: ParserState, event: Event): StepResul
|
||||
]
|
||||
}
|
||||
|
||||
const onFunctionCallArgumentsDelta = Effect.fnUntraced(function* (
|
||||
const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgumentsDelta")(function* (
|
||||
state: ParserState,
|
||||
event: Event,
|
||||
) {
|
||||
@@ -1183,7 +1173,7 @@ const onFunctionCallArgumentsDelta = Effect.fnUntraced(function* (
|
||||
return [{ ...state, lifecycle, tools: result.tools }, events] satisfies StepResult
|
||||
})
|
||||
|
||||
const onOutputItemDone = Effect.fnUntraced(function* (
|
||||
const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
||||
state: ParserState,
|
||||
item: NormalizedEvent["item"],
|
||||
) {
|
||||
@@ -1319,7 +1309,7 @@ const onOutputItemDone = Effect.fnUntraced(function* (
|
||||
return [state, NO_EVENTS] satisfies StepResult
|
||||
})
|
||||
|
||||
const onResponseFinish = Effect.fnUntraced(function* (state: ParserState, event: Event) {
|
||||
const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (state: ParserState, event: Event) {
|
||||
let current = state
|
||||
const events: LLMEvent[] = []
|
||||
if (event.type === "response.completed") {
|
||||
|
||||
@@ -65,7 +65,7 @@ const ExtraContent = Schema.Struct({
|
||||
})
|
||||
const decodeExtraContent = (value: unknown) => Option.getOrUndefined(Schema.decodeUnknownOption(ExtraContent)(value))
|
||||
|
||||
export const OpenAIChatAssistantToolCall = Schema.Struct({
|
||||
const OpenAIChatAssistantToolCall = Schema.Struct({
|
||||
id: Schema.String,
|
||||
type: Schema.tag("function"),
|
||||
function: Schema.Struct({
|
||||
@@ -134,7 +134,7 @@ const OpenAIChatUserContent = Schema.Union([
|
||||
])
|
||||
type OpenAIChatUserContent = Schema.Schema.Type<typeof OpenAIChatUserContent>
|
||||
|
||||
export const OpenAIChatMessage = Schema.Union([
|
||||
const OpenAIChatMessage = Schema.Union([
|
||||
Schema.Struct({
|
||||
role: Schema.Literal("system"),
|
||||
content: Schema.Union([Schema.String, Schema.Array(OpenAIChatUserContent)]),
|
||||
@@ -200,7 +200,7 @@ export type OpenAIChatBody = Schema.Schema.Type<typeof OpenAIChatBody>
|
||||
// The event schema is one decoded SSE `data:` payload. `Framing.sse` splits the
|
||||
// byte stream into strings, then `Protocol.jsonEvent` decodes each string into
|
||||
// this provider-native event shape.
|
||||
export const OpenAIChatUsage = Schema.StructWithRest(
|
||||
const OpenAIChatUsage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
prompt_tokens: optionalNull(Schema.Number),
|
||||
completion_tokens: optionalNull(Schema.Number),
|
||||
@@ -238,7 +238,7 @@ const OpenAIChatToolCallDeltaFunction = Schema.Struct({
|
||||
arguments: optionalNull(Schema.String),
|
||||
})
|
||||
|
||||
export const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
index: optionalNull(Schema.Number),
|
||||
id: optionalNull(Schema.String),
|
||||
function: optionalNull(OpenAIChatToolCallDeltaFunction),
|
||||
@@ -246,7 +246,7 @@ export const OpenAIChatToolCallDelta = Schema.Struct({
|
||||
})
|
||||
type OpenAIChatToolCallDelta = Schema.Schema.Type<typeof OpenAIChatToolCallDelta>
|
||||
|
||||
export const OpenAIChatDelta = Schema.StructWithRest(
|
||||
const OpenAIChatDelta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
content: optionalNull(Schema.String),
|
||||
refusal: optionalNull(Schema.String),
|
||||
@@ -259,7 +259,7 @@ export const OpenAIChatDelta = Schema.StructWithRest(
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
|
||||
export const OpenAIChatChoice = Schema.StructWithRest(
|
||||
const OpenAIChatChoice = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
delta: optionalNull(OpenAIChatDelta),
|
||||
finish_reason: optionalNull(Schema.String),
|
||||
@@ -326,8 +326,6 @@ export interface ParserState {
|
||||
interface LoweringOptions {
|
||||
readonly cacheControl?: (cache: CacheHint | undefined) => OpenAIChatCacheControl | undefined
|
||||
readonly toolCallID?: (id: string) => string
|
||||
/** Project provider-specific fields from the exact source, even when other messages are dropped during lowering. */
|
||||
readonly assistant?: (source: LLMRequest["messages"][number], message: OpenAIChatMessage) => OpenAIChatMessage
|
||||
}
|
||||
|
||||
const lowerTool = (tool: ToolDefinition, options: LoweringOptions, supportsStrictMode: boolean): OpenAIChatTool => ({
|
||||
@@ -362,7 +360,7 @@ const lowerToolCall = (
|
||||
extra_content: decodeExtraContent(part.providerMetadata?.[options.providerMetadataKey]?.extraContent),
|
||||
})
|
||||
|
||||
const lowerMedia = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
const lowerMedia = Effect.fn("OpenAIChat.lowerMedia")(function* (part: MediaPart) {
|
||||
// Chat Completions accepts PDFs, and no other documents, as inline `file` parts; file URLs are not supported.
|
||||
if (part.media.mediaType.toLowerCase() === "application/pdf")
|
||||
return {
|
||||
@@ -408,7 +406,7 @@ const lowerReasoningDetail = (detail: ReasoningDetail) => {
|
||||
|
||||
const isKimiDetail = (detail: { readonly type: string }) => detail.type === "summary" || detail.type === "encrypted"
|
||||
|
||||
const lowerUserMessage = Effect.fnUntraced(function* (
|
||||
const lowerUserMessage = Effect.fn("OpenAIChat.lowerUserMessage")(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
options: LoweringOptions,
|
||||
) {
|
||||
@@ -432,7 +430,7 @@ const lowerUserMessage = Effect.fnUntraced(function* (
|
||||
return { role: "user" as const, content }
|
||||
})
|
||||
|
||||
const lowerAssistantMessage = Effect.fnUntraced(function* (
|
||||
const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
configuredField: string | undefined,
|
||||
requireReasoning: boolean,
|
||||
@@ -497,7 +495,7 @@ const lowerAssistantMessage = Effect.fnUntraced(function* (
|
||||
return { ...result, [field]: reasoningText }
|
||||
})
|
||||
|
||||
const lowerToolMessages = Effect.fnUntraced(function* (
|
||||
const lowerToolMessages = Effect.fn("OpenAIChat.lowerToolMessages")(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
options: LoweringOptions,
|
||||
) {
|
||||
@@ -534,21 +532,19 @@ const toolMessage = (toolCallID: string, text: string, cacheControl: OpenAIChatC
|
||||
content: cacheControl === undefined ? text : [{ type: "text" as const, text, cache_control: cacheControl }],
|
||||
})
|
||||
|
||||
const lowerMessage = Effect.fnUntraced(function* (
|
||||
const lowerMessage = Effect.fn("OpenAIChat.lowerMessage")(function* (
|
||||
message: OpenAIChatRequestMessage,
|
||||
reasoningField: string | undefined,
|
||||
requireReasoning: boolean,
|
||||
options: LoweringOptions & { readonly providerMetadataKey: string },
|
||||
) {
|
||||
if (message.role === "user") return [yield* lowerUserMessage(message, options)]
|
||||
if (message.role === "assistant") {
|
||||
const lowered = yield* lowerAssistantMessage(message, reasoningField, requireReasoning, options)
|
||||
return [options.assistant?.(message, lowered) ?? lowered]
|
||||
}
|
||||
if (message.role === "assistant")
|
||||
return [yield* lowerAssistantMessage(message, reasoningField, requireReasoning, options)]
|
||||
return (yield* lowerToolMessages(message, options)).messages
|
||||
})
|
||||
|
||||
const lowerMessages = Effect.fnUntraced(function* (request: LLMRequest, options: LoweringOptions) {
|
||||
const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request: LLMRequest, options: LoweringOptions) {
|
||||
const system: OpenAIChatMessage[] =
|
||||
request.system.length === 0
|
||||
? []
|
||||
@@ -859,7 +855,7 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (
|
||||
// Streaming parsers are small state machines: every event returns a new state
|
||||
// plus the common `LLMEvent`s produced by that event. Tool calls are accumulated
|
||||
// because OpenAI streams JSON arguments across multiple deltas.
|
||||
const mapFinishReason = Effect.fnUntraced(function* (event: OpenAIChatEvent, reason: string) {
|
||||
const mapFinishReason = Effect.fn("OpenAIChat.mapFinishReason")(function* (event: OpenAIChatEvent, reason: string) {
|
||||
switch (reason) {
|
||||
case "error":
|
||||
return yield* new AIError({
|
||||
@@ -1218,7 +1214,7 @@ const step = (state: ParserState, event: OpenAIChatEvent) =>
|
||||
] as const
|
||||
})
|
||||
|
||||
export const finishEvents = Effect.fnUntraced(function* (state: ParserState) {
|
||||
const finishEvents = Effect.fn("OpenAIChat.finishEvents")(function* (state: ParserState) {
|
||||
if (state.finishReason === undefined && state.requireFinishReason)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
|
||||
@@ -208,7 +208,7 @@ const eventImage = (frame: string, label: string, data: string, format: string,
|
||||
info: info(format, size),
|
||||
})
|
||||
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fn("OpenAIImages.onEvent")(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
const format = event.output_format
|
||||
if ("partial_image_index" in event) {
|
||||
@@ -229,7 +229,7 @@ const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
] as const
|
||||
})
|
||||
|
||||
const onDocument = Effect.fnUntraced(function* (frame: Exclude<Frame, string>) {
|
||||
const onDocument = Effect.fn("OpenAIImages.onDocument")(function* (frame: Exclude<Frame, string>) {
|
||||
const invalid = (message: string, cause?: unknown) => route.frameError(message, frame.document, cause)
|
||||
const decoded = yield* decodeDocument(frame.document).pipe(
|
||||
Effect.mapError((cause) => invalid(`${route.name} returned an invalid response`, cause)),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Headers } from "effect/http"
|
||||
import { Route } from "../route/client.js"
|
||||
import { Auth } from "../route/auth.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
@@ -157,7 +158,7 @@ const nativeImageTool = (tool: ToolDefinition) => {
|
||||
return Schema.is(OpenAIResponsesImageGenerationTool)(native) ? native : undefined
|
||||
}
|
||||
|
||||
const lowerTool = Effect.fnUntraced(function* (tool: ToolDefinition) {
|
||||
const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool: ToolDefinition) {
|
||||
const native = nativeImageToolInput(tool)
|
||||
if (native !== undefined) {
|
||||
if (Schema.is(OpenAIResponsesImageGenerationTool)(native)) return native
|
||||
@@ -168,7 +169,7 @@ const lowerTool = Effect.fnUntraced(function* (tool: ToolDefinition) {
|
||||
|
||||
// Native namespaces hold only function tools, so deeper levels flatten into
|
||||
// the leaf names the same way non-native protocols flatten the whole tree.
|
||||
const lowerToolEntry = Effect.fnUntraced(function* (tool: ToolEntry) {
|
||||
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool: ToolEntry) {
|
||||
if (tool.type === "tool") return yield* lowerTool(tool)
|
||||
// OpenAI requires a namespace description; fall back to a generic one so a
|
||||
// missing description never blocks the request.
|
||||
@@ -237,10 +238,10 @@ const checkpointBody = {
|
||||
}),
|
||||
}
|
||||
|
||||
const hostedToolResult = Effect.fnUntraced(function* (item: ResponsesHostedTools.Item) {
|
||||
const hostedToolResult = Effect.fn("OpenAIResponses.hostedToolResult")(function* (item: ResponsesHostedTools.Item) {
|
||||
const isError = item.error !== undefined && item.error !== null
|
||||
if (item.type === "image_generation_call" && item.result) {
|
||||
yield* Effect.fromResult(Encoding.decodeBase64(item.result)).pipe(
|
||||
yield* Effect.fromResult(Base64.decode(item.result)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.eventError(ADAPTER, "OpenAI Responses returned invalid image base64", undefined, cause),
|
||||
),
|
||||
|
||||
@@ -94,7 +94,7 @@ const fromRequest = Effect.fn("OpenAISpeech.fromRequest")(function* (request: Me
|
||||
|
||||
const isSse = (body: MediaProtocol.Body) => body.type === "json" && body.value.stream_format === "sse"
|
||||
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fn("OpenAISpeech.onEvent")(function* (state: State, frame: string) {
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "speech.audio.delta") return SpeechStream.delta(state, event.audio)
|
||||
const usage = event.usage
|
||||
|
||||
@@ -210,7 +210,7 @@ const segment = (value: Schema.Schema.Type<typeof Segment>): TranscriptionSegmen
|
||||
speaker: value.speaker,
|
||||
})
|
||||
|
||||
const onEvent = Effect.fnUntraced(function* (state: State, frame: string) {
|
||||
const onEvent = Effect.fn("OpenAITranscription.onEvent")(function* (state: State, frame: string) {
|
||||
if (!EVENT_TYPES.has((yield* decodeEventType(frame)).type)) return [state, []] as const
|
||||
const event = yield* decodeEvent(frame)
|
||||
if (event.type === "error")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tool } from "@opencode/schema/tool"
|
||||
import { Effect, Option, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Media } from "../media.js"
|
||||
import {
|
||||
InvalidProviderOutputError,
|
||||
@@ -154,7 +154,7 @@ export const wrapSystemUpdate = (parts: ReadonlyArray<{ readonly text: string }>
|
||||
* raw retrieved, tool, or web content into privileged updates: keep untrusted
|
||||
* data in ordinary user/tool messages instead.
|
||||
*/
|
||||
export const systemUpdateText = Effect.fnUntraced(function* (
|
||||
export const systemUpdateText = Effect.fn("ProviderShared.systemUpdateText")(function* (
|
||||
route: string,
|
||||
message: LLMRequest["messages"][number],
|
||||
) {
|
||||
@@ -167,7 +167,7 @@ export const systemUpdateText = Effect.fnUntraced(function* (
|
||||
})
|
||||
|
||||
/** Lower an unsupported privileged update into visible, in-order user text. */
|
||||
export const wrappedSystemUpdate = Effect.fnUntraced(function* (
|
||||
export const wrappedSystemUpdate = Effect.fn("ProviderShared.wrappedSystemUpdate")(function* (
|
||||
route: string,
|
||||
message: LLMRequest["messages"][number],
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
@@ -82,7 +82,7 @@ const endpoint = (model: string) => (model.startsWith("sd3") ? "sd3" : model)
|
||||
|
||||
const RESERVED_FORM_FIELDS = new Set(["image", "prompt", "mode", "model"])
|
||||
|
||||
const form = Effect.fnUntraced(function* (
|
||||
const form = Effect.fn("StabilityImages.form")(function* (
|
||||
identity: MediaProtocol.Identity,
|
||||
fields: Record<string, unknown>,
|
||||
native: Record<string, unknown> | undefined,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AwsV4Signer } from "aws4fetch"
|
||||
import { Effect } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Headers } from "effect/http"
|
||||
import { Auth, type AuthInput } from "../../route/auth.js"
|
||||
import { AIError, AuthenticationError } from "../../schema/index.js"
|
||||
import { ProviderShared } from "../shared.js"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Effect, Encoding, Schema } from "effect"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import type { MediaPart } from "../../schema/index.js"
|
||||
import { ProviderShared } from "../shared.js"
|
||||
|
||||
@@ -76,14 +77,14 @@ function documentName(filename: string | undefined, names: Set<string>) {
|
||||
return name
|
||||
}
|
||||
|
||||
const mediaBase64 = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
const mediaBase64 = Effect.fn("BedrockMedia.mediaBase64")(function* (part: MediaPart) {
|
||||
const media = yield* ProviderShared.requireInlineMedia("Bedrock Converse", part.media)
|
||||
const bytes = yield* Effect.fromResult(Encoding.decodeBase64(media.base64)).pipe(
|
||||
const bytes = yield* Effect.fromResult(Base64.decode(media.base64)).pipe(
|
||||
Effect.mapError((cause) =>
|
||||
ProviderShared.invalidRequest("Bedrock Converse media data must be valid base64", cause),
|
||||
),
|
||||
)
|
||||
return Encoding.encodeBase64(bytes)
|
||||
return Base64.encode(bytes)
|
||||
})
|
||||
|
||||
// Route by MIME. Known image/document formats lower into a typed block; anything
|
||||
@@ -91,7 +92,7 @@ const mediaBase64 = Effect.fnUntraced(function* (part: MediaPart) {
|
||||
// document block. Image MIME types not in `IMAGE_FORMATS` (e.g. `image/svg+xml`)
|
||||
// get an image-specific error so the caller knows it's a format-support issue,
|
||||
// not a kind-detection issue.
|
||||
export const lower = Effect.fnUntraced(function* (part: MediaPart, documentNames: Set<string>) {
|
||||
export const lower = Effect.fn("BedrockMedia.lower")(function* (part: MediaPart, documentNames: Set<string>) {
|
||||
const mime = part.media.mediaType.toLowerCase()
|
||||
const imageFormat = IMAGE_FORMATS[mime as keyof typeof IMAGE_FORMATS]
|
||||
if (imageFormat) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../../generation.js"
|
||||
import type { Media } from "../../media.js"
|
||||
import { MediaProtocol } from "../../route/media-protocol.js"
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Effect, Option, Schema } from "effect"
|
||||
import { Protocol } from "../../route/protocol.js"
|
||||
import { LLMEvent, mergeJsonRecords, type AIError, type LLMRequest } from "../../schema/index.js"
|
||||
import { JsonObject, lenient } from "../shared.js"
|
||||
|
||||
interface ParserState<Inner> {
|
||||
readonly inner: Inner
|
||||
readonly gateway?: Record<string, unknown>
|
||||
}
|
||||
|
||||
const GatewayHolder = Schema.Struct({
|
||||
provider_metadata: lenient(
|
||||
Schema.Struct({
|
||||
gateway: lenient(JsonObject),
|
||||
}),
|
||||
),
|
||||
})
|
||||
|
||||
const GatewayEvent = Schema.Struct({
|
||||
...GatewayHolder.fields,
|
||||
response: lenient(GatewayHolder),
|
||||
choices: lenient(
|
||||
Schema.Array(
|
||||
Schema.Struct({
|
||||
delta: lenient(GatewayHolder),
|
||||
}),
|
||||
),
|
||||
),
|
||||
})
|
||||
const decodeGatewayEvent = Schema.decodeUnknownOption(GatewayEvent)
|
||||
|
||||
function attachGatewayMetadata(
|
||||
events: ReadonlyArray<LLMEvent>,
|
||||
gateway: Record<string, unknown> | undefined,
|
||||
): ReadonlyArray<LLMEvent> {
|
||||
if (!gateway || !events.some(LLMEvent.is.finish)) return events
|
||||
return events.map((event) =>
|
||||
LLMEvent.is.finish(event) ? { ...event, providerMetadata: { ...event.providerMetadata, gateway } } : event,
|
||||
)
|
||||
}
|
||||
|
||||
export function gatewayProtocol<Body, Event, State>(
|
||||
protocol: Protocol<Body, string, Event, State>,
|
||||
input: {
|
||||
readonly id: string
|
||||
readonly prepare: (
|
||||
request: LLMRequest,
|
||||
) => Effect.Effect<{ readonly request: LLMRequest; readonly body: Record<string, unknown> }, AIError>
|
||||
},
|
||||
) {
|
||||
const initial = (request: LLMRequest): ParserState<State> => ({
|
||||
inner: protocol.stream.initial(request),
|
||||
})
|
||||
const onHalt = protocol.stream.onHalt
|
||||
|
||||
return Protocol.make({
|
||||
id: input.id,
|
||||
body: {
|
||||
schema: JsonObject,
|
||||
from: Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const prepared = yield* input.prepare(request)
|
||||
const body = yield* protocol.body.from(prepared.request)
|
||||
return { ...body, ...prepared.body }
|
||||
}),
|
||||
},
|
||||
supportsEffortUpdates: protocol.supportsEffortUpdates,
|
||||
sanitizer: protocol.sanitizer,
|
||||
stream: {
|
||||
event: protocol.stream.event,
|
||||
initial,
|
||||
step: Effect.fnUntraced(function* (state: ParserState<State>, event: Event) {
|
||||
const decoded = Option.getOrUndefined(decodeGatewayEvent(event))
|
||||
const gateway = decoded
|
||||
? mergeJsonRecords(
|
||||
state.gateway,
|
||||
decoded.provider_metadata?.gateway,
|
||||
decoded.response?.provider_metadata?.gateway,
|
||||
...(decoded.choices ?? []).map((choice) => choice.delta?.provider_metadata?.gateway),
|
||||
)
|
||||
: state.gateway
|
||||
const [inner, events] = yield* protocol.stream.step(state.inner, event)
|
||||
return [{ inner, gateway }, attachGatewayMetadata(events, gateway)] as const
|
||||
}),
|
||||
terminal: protocol.stream.terminal,
|
||||
onHalt: onHalt
|
||||
? (state) => onHalt(state.inner).pipe(Effect.map((events) => attachGatewayMetadata(events, state.gateway)))
|
||||
: undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Effect, Encoding } from "effect"
|
||||
import { Effect } from "effect"
|
||||
import { Base64 } from "effect/encoding"
|
||||
import { Media } from "../../media.js"
|
||||
import type { MediaProtocol } from "../../route/media-protocol.js"
|
||||
import { mergeJsonRecords, type AIError, type ProviderID } from "../../schema/index.js"
|
||||
@@ -10,7 +11,7 @@ export const inlineBytes = (route: string, asset: Media.Asset): Effect.Effect<Ui
|
||||
if (asset.source.type === "bytes") return Effect.succeed(asset.source.data)
|
||||
const inline = asset.inline()
|
||||
if (!inline) return Effect.fail(ProviderShared.inlineRequired(route, asset))
|
||||
return Effect.fromResult(Encoding.decodeBase64(inline.base64)).pipe(
|
||||
return Effect.fromResult(Base64.decode(inline.base64)).pipe(
|
||||
Effect.mapError((cause) => ProviderShared.invalidRequest(`${route} media contains invalid base64 data`, cause)),
|
||||
)
|
||||
}
|
||||
@@ -52,7 +53,7 @@ export const decodedAsset = (
|
||||
mediaType: string | undefined,
|
||||
options?: Media.AssetOptions,
|
||||
) =>
|
||||
Effect.fromResult(Encoding.decodeBase64(data)).pipe(
|
||||
Effect.fromResult(Base64.decode(data)).pipe(
|
||||
Effect.mapError((cause) => invalid(`${label} contains invalid base64 data`, cause)),
|
||||
Effect.map((bytes) => Media.bytes(bytes, mediaType, options)),
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ interface State {
|
||||
readonly responseID?: string
|
||||
}
|
||||
|
||||
const onOutputItem = Effect.fnUntraced(function* (
|
||||
const onOutputItem = Effect.fn("ResponsesCheckpoint.onOutputItem")(function* (
|
||||
state: State,
|
||||
input: OpenResponses.Event,
|
||||
) {
|
||||
@@ -63,7 +63,7 @@ export const make = <Body>(body: RouteBody<Body>): TriggerCompactOperation =>
|
||||
checkpoints: {},
|
||||
}),
|
||||
terminal: OpenResponses.terminal,
|
||||
step: Effect.fnUntraced(function* (state: State, event: OpenResponses.Event) {
|
||||
step: Effect.fn("ResponsesCheckpoint.step")(function* (state: State, event: OpenResponses.Event) {
|
||||
if (event.response?.id && state.responseID && event.response.id !== state.responseID)
|
||||
return yield* ProviderShared.eventError(source.id, "Compaction response ID changed during execution")
|
||||
if (event.type === "response.created") return [{ ...state, responseID: event.response?.id }, []] as const
|
||||
|
||||
@@ -33,7 +33,7 @@ export const onDone: (
|
||||
state: OpenResponses.ParserState,
|
||||
item: Item,
|
||||
tools: Definitions,
|
||||
) => Effect.Effect<OpenResponses.StepResult, AIError> = Effect.fnUntraced(
|
||||
) => Effect.Effect<OpenResponses.StepResult, AIError> = Effect.fn("ResponsesHostedTools.onDone")(
|
||||
function* (state, item, tools) {
|
||||
const tool = tools[item.type]
|
||||
if (!tool) return [state, []] satisfies OpenResponses.StepResult
|
||||
|
||||
@@ -60,21 +60,14 @@ const inputStart = (tool: PendingTool) =>
|
||||
providerMetadata: tool.providerMetadata,
|
||||
})
|
||||
|
||||
const inputDelta = (tool: PendingTool, text: string): LLMEvent => {
|
||||
const raw = tool.input
|
||||
let parsed: unknown
|
||||
return {
|
||||
...LLMEvent.toolInputDelta({
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
namespace: tool.namespace,
|
||||
text,
|
||||
}),
|
||||
get input() {
|
||||
return (parsed ??= Option.getOrElse(parsePartialInput(raw), () => ({})))
|
||||
},
|
||||
}
|
||||
}
|
||||
const inputDelta = (tool: PendingTool, text: string) =>
|
||||
LLMEvent.toolInputDelta({
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
namespace: tool.namespace,
|
||||
text,
|
||||
input: Option.getOrElse(parsePartialInput(tool.input), () => ({})),
|
||||
})
|
||||
|
||||
const toolCall = (route: string, tool: PendingTool, inputOverride?: string) => {
|
||||
const raw = inputOverride ?? tool.input
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { AIError, LLMEvent, type LanguageModelCompatibility, type LLMRequest } from "../schema/index.js"
|
||||
import { classifyProviderFailure } from "../provider-error.js"
|
||||
import { OpenAIChat } from "./openai-chat.js"
|
||||
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js"
|
||||
import { cacheControl } from "./utils/cache.js"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public options and request body
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | (string & {})
|
||||
|
||||
const Parameters = Schema.Struct({
|
||||
enableWebSearch: Schema.optional(Schema.String),
|
||||
enableWebScraping: Schema.optional(Schema.Boolean),
|
||||
enableWebCitations: Schema.optional(Schema.Boolean),
|
||||
enableXSearch: Schema.optional(Schema.Boolean),
|
||||
stripThinkingResponse: Schema.optional(Schema.Boolean),
|
||||
disableThinking: Schema.optional(Schema.Boolean),
|
||||
includeVeniceSystemPrompt: Schema.optional(Schema.Boolean),
|
||||
characterSlug: Schema.optional(Schema.String),
|
||||
includeSearchResultsInStream: Schema.optional(Schema.Boolean),
|
||||
returnSearchResultsAsDocuments: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
|
||||
const Reasoning = Schema.Struct({
|
||||
effort: Schema.optional(Schema.String),
|
||||
enabled: Schema.optional(Schema.Boolean),
|
||||
summary: Schema.optional(Schema.String),
|
||||
})
|
||||
|
||||
export type OptionsInput = {
|
||||
readonly reasoningEffort?: ReasoningEffort
|
||||
readonly reasoning?: {
|
||||
readonly effort?: ReasoningEffort
|
||||
readonly enabled?: boolean
|
||||
readonly summary?: "auto" | "concise" | "detailed" | (string & {})
|
||||
}
|
||||
readonly veniceParameters?: Omit<typeof Parameters.Type, "enableWebSearch"> & {
|
||||
readonly enableWebSearch?: "off" | "on" | "auto" | (string & {})
|
||||
}
|
||||
readonly promptCacheKey?: string
|
||||
readonly promptCacheRetention?: "default" | "extended" | "24h" | (string & {})
|
||||
readonly parallelToolCalls?: boolean
|
||||
readonly maxCompletionTokens?: number
|
||||
readonly maxTokens?: number
|
||||
readonly minP?: number
|
||||
readonly repetitionPenalty?: number
|
||||
readonly stopTokenIds?: readonly number[]
|
||||
readonly logprobs?: boolean
|
||||
readonly topLogprobs?: number
|
||||
readonly maxTemp?: number
|
||||
readonly minTemp?: number
|
||||
readonly responseFormat?: Readonly<Record<string, unknown>>
|
||||
readonly user?: string
|
||||
}
|
||||
|
||||
const Options = Schema.Struct({
|
||||
reasoningEffort: Schema.optional(Schema.String),
|
||||
reasoning: Schema.optional(Reasoning),
|
||||
veniceParameters: Schema.optional(Parameters),
|
||||
promptCacheKey: Schema.optional(Schema.String),
|
||||
promptCacheRetention: Schema.optional(Schema.String),
|
||||
parallelToolCalls: Schema.optional(Schema.Boolean),
|
||||
maxCompletionTokens: Schema.optional(Schema.Number),
|
||||
maxTokens: Schema.optional(Schema.Number),
|
||||
minP: Schema.optional(Schema.Number),
|
||||
repetitionPenalty: Schema.optional(Schema.Number),
|
||||
stopTokenIds: Schema.optional(Schema.Array(Schema.Number)),
|
||||
logprobs: Schema.optional(Schema.Boolean),
|
||||
topLogprobs: Schema.optional(Schema.Number),
|
||||
maxTemp: Schema.optional(Schema.Number),
|
||||
minTemp: Schema.optional(Schema.Number),
|
||||
responseFormat: Schema.optional(JsonObject),
|
||||
user: Schema.optional(Schema.String),
|
||||
})
|
||||
|
||||
const ToolCall = Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatAssistantToolCall.fields,
|
||||
thought_signature: Schema.optional(Schema.String),
|
||||
})
|
||||
const Assistant = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatMessage.cases.assistant.schema.fields,
|
||||
tool_calls: optionalArray(ToolCall),
|
||||
thought_signature: Schema.optional(Schema.String),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Messages = Schema.Array(
|
||||
Schema.Union([
|
||||
OpenAIChat.OpenAIChatMessage.cases.system,
|
||||
OpenAIChat.OpenAIChatMessage.cases.user,
|
||||
Assistant,
|
||||
OpenAIChat.OpenAIChatMessage.cases.tool,
|
||||
]),
|
||||
)
|
||||
const Body = Schema.Struct({
|
||||
...OpenAIChat.bodyFields,
|
||||
messages: Messages,
|
||||
reasoning: Schema.optional(Reasoning),
|
||||
venice_parameters: Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Boolean])),
|
||||
prompt_cache_retention: Options.fields.promptCacheRetention,
|
||||
parallel_tool_calls: Options.fields.parallelToolCalls,
|
||||
min_p: Options.fields.minP,
|
||||
top_k: Schema.optional(Schema.Number),
|
||||
repetition_penalty: Options.fields.repetitionPenalty,
|
||||
stop_token_ids: Options.fields.stopTokenIds,
|
||||
logprobs: Options.fields.logprobs,
|
||||
top_logprobs: Options.fields.topLogprobs,
|
||||
max_temp: Options.fields.maxTemp,
|
||||
min_temp: Options.fields.minTemp,
|
||||
response_format: Options.fields.responseFormat,
|
||||
user: Options.fields.user,
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Streaming schemas and state
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const ToolDelta = Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatToolCallDelta.fields,
|
||||
thought_signature: optionalNull(Schema.String),
|
||||
})
|
||||
const Delta = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatDelta.schema.fields,
|
||||
tool_calls: optionalNull(Schema.Array(ToolDelta)),
|
||||
thought_signature: optionalNull(Schema.String),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Choice = Schema.StructWithRest(
|
||||
Schema.Struct({ ...OpenAIChat.OpenAIChatChoice.schema.fields, delta: optionalNull(Delta) }),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Usage = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatUsage.schema.fields,
|
||||
prompt_tokens_details: optionalNull(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
cached_tokens: optionalNull(Schema.Number),
|
||||
cache_write_tokens: optionalNull(Schema.Number),
|
||||
cache_creation_input_tokens: optionalNull(Schema.Number),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
),
|
||||
),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
const Event = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
...OpenAIChat.OpenAIChatEvent.schema.fields,
|
||||
choices: optionalNull(Schema.Array(Choice)),
|
||||
usage: optionalNull(Usage),
|
||||
error: optionalNull(Schema.Union([Schema.String, OpenAIChat.OpenAIChatEvent.schema.fields.error.schema])),
|
||||
issues: optionalArray(
|
||||
Schema.Struct({
|
||||
message: Schema.String,
|
||||
path: Schema.optional(Schema.Array(Schema.Union([Schema.String, Schema.Number]))),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
[Schema.Record(Schema.String, Schema.Unknown)],
|
||||
)
|
||||
|
||||
interface State {
|
||||
readonly shared: OpenAIChat.ParserState
|
||||
readonly pending: string
|
||||
readonly reasoning: string
|
||||
readonly encrypted: boolean
|
||||
readonly signature?: string
|
||||
readonly tools: Readonly<Record<string, string>>
|
||||
}
|
||||
|
||||
const MARKER = "__ENCRYPTED_REASONING__"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Request lowering
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const fromRequest = Effect.fn("VeniceChat.fromRequest")(function* (request: LLMRequest) {
|
||||
const options = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(request.providerOptions ?? {})
|
||||
const body = yield* OpenAIChat.fromRequest(request, {
|
||||
cacheControl: cacheControl(),
|
||||
assistant: (source, message) => {
|
||||
if (message.role !== "assistant") return message
|
||||
const parts = source.content.filter(
|
||||
(part) => part.type === "text" || part.type === "reasoning" || part.type === "tool-call",
|
||||
)
|
||||
const calls = source.content.filter((part) => part.type === "tool-call")
|
||||
const signature = parts
|
||||
.map((part) => part.providerMetadata?.venice?.messageThoughtSignature)
|
||||
.find((value) => typeof value === "string")
|
||||
const raw = parts
|
||||
.map((part) => part.providerMetadata?.venice?.encryptedReasoningContent)
|
||||
.find((value) => typeof value === "string")
|
||||
return {
|
||||
...message,
|
||||
...(signature === undefined ? {} : { thought_signature: signature }),
|
||||
...(raw === undefined ? {} : { reasoning_content: raw }),
|
||||
tool_calls: message.tool_calls?.map((call, index) => {
|
||||
const signature = calls[index]?.providerMetadata?.venice?.thoughtSignature
|
||||
return { ...call, ...(typeof signature === "string" ? { thought_signature: signature } : {}) }
|
||||
}),
|
||||
}
|
||||
},
|
||||
})
|
||||
return {
|
||||
...body,
|
||||
max_completion_tokens: options.maxCompletionTokens ?? options.maxTokens ?? request.generation?.maxTokens,
|
||||
reasoning_effort: undefined,
|
||||
reasoning:
|
||||
options.reasoningEffort === undefined
|
||||
? options.reasoning
|
||||
: { ...options.reasoning, effort: options.reasoningEffort },
|
||||
// Match the previous Venice SDK default, not the gateway's added prompt.
|
||||
venice_parameters: Object.fromEntries(
|
||||
Object.entries({
|
||||
...options.veniceParameters,
|
||||
includeVeniceSystemPrompt: options.veniceParameters?.includeVeniceSystemPrompt ?? false,
|
||||
})
|
||||
.filter(([, value]) => value !== undefined)
|
||||
.map(([key, value]) => [key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`), value]),
|
||||
),
|
||||
prompt_cache_retention: options.promptCacheRetention,
|
||||
parallel_tool_calls: options.parallelToolCalls,
|
||||
min_p: options.minP,
|
||||
top_k: request.generation?.topK,
|
||||
repetition_penalty: options.repetitionPenalty,
|
||||
stop_token_ids: options.stopTokenIds,
|
||||
logprobs: options.logprobs,
|
||||
top_logprobs: options.topLogprobs,
|
||||
max_temp: options.maxTemp,
|
||||
min_temp: options.minTemp,
|
||||
response_format: options.responseFormat,
|
||||
user: options.user,
|
||||
}
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Venice normalization around the shared Chat state machine
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const step = Effect.fn("VeniceChat.step")(function* (state: State, event: typeof Event.Type) {
|
||||
if (typeof event.error === "string")
|
||||
return yield* new AIError({
|
||||
reason: classifyProviderFailure({
|
||||
message: [
|
||||
event.error,
|
||||
...(event.issues ?? []).map(
|
||||
(issue) => `${issue.path?.length ? `${issue.path.join(".")}: ` : ""}${issue.message}`,
|
||||
),
|
||||
].join("; "),
|
||||
rawBody: ProviderShared.encodeJson(event),
|
||||
}),
|
||||
})
|
||||
const delta = event.choices?.[0]?.delta
|
||||
const scalar = delta?.reasoning_content ?? ""
|
||||
const text = state.pending + scalar
|
||||
const marker = text.indexOf(MARKER)
|
||||
const pending =
|
||||
marker >= 0 || state.encrypted
|
||||
? 0
|
||||
: (Array.from({ length: Math.min(text.length, MARKER.length - 1) }, (_, index) => index + 1)
|
||||
.filter((length) => text.endsWith(MARKER.slice(0, length)))
|
||||
.at(-1) ?? 0)
|
||||
const visible = state.encrypted ? "" : marker >= 0 ? text.slice(0, marker) : text.slice(0, text.length - pending)
|
||||
const result = yield* OpenAIChat.protocol.stream.step(state.shared, {
|
||||
...event,
|
||||
error: event.error,
|
||||
usage: event.usage
|
||||
? {
|
||||
...event.usage,
|
||||
prompt_tokens_details: event.usage.prompt_tokens_details
|
||||
? {
|
||||
...event.usage.prompt_tokens_details,
|
||||
cache_write_tokens:
|
||||
event.usage.prompt_tokens_details.cache_write_tokens ??
|
||||
event.usage.prompt_tokens_details.cache_creation_input_tokens,
|
||||
}
|
||||
: event.usage.prompt_tokens_details,
|
||||
}
|
||||
: event.usage,
|
||||
choices: event.choices?.map((choice, index) =>
|
||||
index === 0 && choice.delta
|
||||
? {
|
||||
...choice,
|
||||
delta: {
|
||||
...choice.delta,
|
||||
reasoning_content: visible || undefined,
|
||||
// Opaque-only scalar reasoning still needs a canonical part for replay.
|
||||
reasoning_details: choice.delta.reasoning_details ?? (marker >= 0 ? [] : undefined),
|
||||
},
|
||||
}
|
||||
: choice,
|
||||
),
|
||||
})
|
||||
const tools = { ...state.tools }
|
||||
for (const call of delta?.tool_calls ?? []) {
|
||||
if (!call.thought_signature) continue
|
||||
const index = call.index ?? result[0].latestToolIndex
|
||||
const id =
|
||||
call.id ?? (index === undefined ? undefined : (result[0].tools[index]?.id ?? result[0].pendingTools[index]?.id))
|
||||
if (id) tools[id] = call.thought_signature
|
||||
}
|
||||
return [
|
||||
{
|
||||
shared: result[0],
|
||||
pending: pending ? text.slice(-pending) : "",
|
||||
reasoning: state.reasoning + scalar,
|
||||
encrypted: state.encrypted || marker >= 0,
|
||||
signature: delta?.thought_signature ?? state.signature,
|
||||
tools,
|
||||
},
|
||||
result[1],
|
||||
] as const
|
||||
})
|
||||
|
||||
const onHalt = Effect.fn("VeniceChat.onHalt")(function* (state: State) {
|
||||
const events = yield* OpenAIChat.finishEvents(state.shared)
|
||||
return events.flatMap((event): LLMEvent[] => {
|
||||
if (
|
||||
event.type !== "reasoning-end" &&
|
||||
event.type !== "text-end" &&
|
||||
event.type !== "tool-call" &&
|
||||
event.type !== "tool-input-end"
|
||||
)
|
||||
return [event]
|
||||
const signature = event.type === "tool-call" || event.type === "tool-input-end" ? state.tools[event.id] : undefined
|
||||
const providerMetadata = {
|
||||
...event.providerMetadata,
|
||||
venice: {
|
||||
...event.providerMetadata?.venice,
|
||||
...(state.signature ? { messageThoughtSignature: state.signature } : {}),
|
||||
...(signature ? { thoughtSignature: signature } : {}),
|
||||
...(event.type === "reasoning-end" && state.encrypted ? { encryptedReasoningContent: state.reasoning } : {}),
|
||||
},
|
||||
}
|
||||
if (event.type === "reasoning-end" && state.pending)
|
||||
return [LLMEvent.reasoningDelta({ id: event.id, text: state.pending }), { ...event, providerMetadata }]
|
||||
return [{ ...event, providerMetadata }]
|
||||
})
|
||||
})
|
||||
|
||||
export const compatibility = {
|
||||
maxTokensField: "max_completion_tokens",
|
||||
supportsStore: false,
|
||||
supportsPromptCacheKey: true,
|
||||
} satisfies LanguageModelCompatibility
|
||||
|
||||
export const protocol = Protocol.make({
|
||||
id: "venice-chat",
|
||||
body: { schema: Body, from: fromRequest },
|
||||
stream: {
|
||||
event: Schema.Union([Schema.Literal("[DONE]"), Protocol.jsonEvent(Event)]),
|
||||
initial: (request): State => ({
|
||||
shared: OpenAIChat.protocol.stream.initial(request),
|
||||
pending: "",
|
||||
reasoning: "",
|
||||
encrypted: false,
|
||||
tools: {},
|
||||
}),
|
||||
step: (state: State, event) => (event === "[DONE]" ? Effect.succeed([state, []] as const) : step(state, event)),
|
||||
terminal: (event) => event === "[DONE]",
|
||||
onHalt,
|
||||
},
|
||||
})
|
||||
|
||||
export * as VeniceChat from "./venice-chat.js"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import type { Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schema } from "effect"
|
||||
import type { HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientResponse } from "effect/http"
|
||||
import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js"
|
||||
import { MediaProtocol } from "../route/media-protocol.js"
|
||||
import { MediaRoute } from "../route/media.js"
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
|
||||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { OpenResponses } from "../protocols/open-responses.js"
|
||||
import { BedrockAuth, type Credentials } from "../protocols/utils/bedrock-auth.js"
|
||||
import { claudeVersion } from "../protocols/utils/claude-model.js"
|
||||
import { ProviderConfigurationError, ProviderID, type ModelID } from "../schema/index.js"
|
||||
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options.js"
|
||||
|
||||
export const id = ProviderID.make("amazon-bedrock")
|
||||
|
||||
export type OpenAIOptionsInput = OpenAIProviderOptionsInput
|
||||
export type MessagesOptionsInput = AnthropicMessages.ProviderOptionsInput
|
||||
|
||||
export type Config = Omit<RouteDefaultsInput, "providerOptions"> & {
|
||||
export type Config = RouteDefaultsInput & {
|
||||
/** Bedrock API key. Falls back to `AWS_BEARER_TOKEN_BEDROCK`; bearer auth takes precedence over SigV4. */
|
||||
readonly apiKey?: string
|
||||
/** `sigv4` ignores `apiKey` fallbacks from the environment; `bearer` requires a token. */
|
||||
@@ -25,11 +20,11 @@ export type Config = Omit<RouteDefaultsInput, "providerOptions"> & {
|
||||
/** Shared config profile for the default credential chain. */
|
||||
readonly profile?: string
|
||||
readonly region?: string
|
||||
readonly providerOptions?: OpenAIProviderOptionsInput | AnthropicMessages.ProviderOptionsInput
|
||||
readonly providerOptions?: OpenAIProviderOptionsInput
|
||||
}
|
||||
|
||||
export type Settings<Options = OpenAIProviderOptionsInput> = ProviderPackage.Settings &
|
||||
Options & {
|
||||
export type Settings = ProviderPackage.Settings &
|
||||
OpenAIProviderOptionsInput & {
|
||||
readonly apiKey?: string
|
||||
readonly auth?: "bearer" | "sigv4"
|
||||
readonly baseURL?: string
|
||||
@@ -39,8 +34,6 @@ export type Settings<Options = OpenAIProviderOptionsInput> = ProviderPackage.Set
|
||||
readonly topP?: number
|
||||
}
|
||||
|
||||
export type MessagesSettings = Settings<AnthropicMessages.ProviderOptionsInput>
|
||||
|
||||
const responsesRoute = Route.make({
|
||||
id: "bedrock-mantle-responses",
|
||||
provider: id,
|
||||
@@ -57,35 +50,12 @@ const chatRoute = OpenAIChat.route.with({
|
||||
providerMetadataKey: "mantle",
|
||||
})
|
||||
|
||||
const messagesRoute = Route.make({
|
||||
id: "bedrock-mantle-messages",
|
||||
provider: id,
|
||||
providerMetadataKey: "mantle",
|
||||
protocol: {
|
||||
...AnthropicMessages.protocol,
|
||||
// Mantle rejects mid-conversation `output_config` on Opus 5.0; support starts at 5.1+.
|
||||
supportsEffortUpdates: (request) => {
|
||||
const override = request.model.compatibility?.supportsEffortUpdates
|
||||
if (override !== undefined) return override
|
||||
const version = claudeVersion(request.model.id)
|
||||
return version !== undefined && (version.major > 5 || (version.major === 5 && version.minor >= 1))
|
||||
},
|
||||
},
|
||||
endpoint: Endpoint.path(AnthropicMessages.PATH),
|
||||
transport: AnthropicMessages.transport<AnthropicMessages.AnthropicMessagesBody>(),
|
||||
headers: () => ({ "anthropic-version": "2023-06-01" }),
|
||||
})
|
||||
export const routes = [responsesRoute, chatRoute]
|
||||
|
||||
export const routes = [responsesRoute, chatRoute, messagesRoute]
|
||||
|
||||
const configuredRoute = <Body, Prepared>(
|
||||
route: Route<Body, Prepared>,
|
||||
input: Config,
|
||||
defaultBaseURL = (region: string) => `https://bedrock-mantle.${region}.api.aws/v1`,
|
||||
) => {
|
||||
const configuredRoute = <Body, Prepared>(route: Route<Body, Prepared>, input: Config) => {
|
||||
const region = BedrockAuth.resolveRegion(input)
|
||||
return route.with({
|
||||
endpoint: { baseURL: input.baseURL ?? defaultBaseURL(region) },
|
||||
endpoint: { baseURL: input.baseURL ?? `https://bedrock-mantle.${region}.api.aws/v1` },
|
||||
auth: BedrockAuth.resolveAuth(input, region, {
|
||||
service: "bedrock-mantle",
|
||||
name: "Bedrock Mantle",
|
||||
@@ -117,11 +87,6 @@ export const configure = (input: Config = {}) => {
|
||||
})
|
||||
const configuredResponsesRoute = configuredRoute(responsesRoute, input)
|
||||
const configuredChatRoute = configuredRoute(chatRoute, input)
|
||||
const configuredMessagesRoute = configuredRoute(
|
||||
messagesRoute,
|
||||
input,
|
||||
(region) => `https://bedrock-mantle.${region}.api.aws/anthropic/v1`,
|
||||
)
|
||||
const modelDefaults = defaults(input)
|
||||
const responses = (modelID: string | ModelID) =>
|
||||
configuredResponsesRoute
|
||||
@@ -131,14 +96,11 @@ export const configure = (input: Config = {}) => {
|
||||
configuredChatRoute
|
||||
.with(withOpenAIOptions(modelID, modelDefaults))
|
||||
.model<OpenAIProviderOptionsInput>({ id: modelID })
|
||||
const messages = (modelID: string | ModelID) =>
|
||||
configuredMessagesRoute.with(modelDefaults).model<AnthropicMessages.ProviderOptionsInput>({ id: modelID })
|
||||
|
||||
return {
|
||||
id,
|
||||
model: responses,
|
||||
chat,
|
||||
messages,
|
||||
responses,
|
||||
configure,
|
||||
}
|
||||
@@ -157,7 +119,7 @@ const fromSettings = ({
|
||||
region,
|
||||
topP,
|
||||
...providerOptions
|
||||
}: Settings<Config["providerOptions"]>) =>
|
||||
}: Settings) =>
|
||||
configure({
|
||||
apiKey,
|
||||
auth,
|
||||
@@ -175,10 +137,6 @@ export const chatModel: ProviderPackage.Definition<Settings, OpenAIProviderOptio
|
||||
modelID,
|
||||
settings,
|
||||
) => fromSettings(settings).chat(modelID)
|
||||
export const messagesModel: ProviderPackage.Definition<
|
||||
MessagesSettings,
|
||||
AnthropicMessages.ProviderOptionsInput
|
||||
>["model"] = (modelID, settings) => fromSettings(settings).messages(modelID)
|
||||
export const responsesModel: ProviderPackage.Definition<Settings, OpenAIProviderOptionsInput>["model"] = (
|
||||
modelID,
|
||||
settings,
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export { messagesModel as model } from "../../amazon-bedrock-mantle.js"
|
||||
export type { MessagesSettings as Settings } from "../../amazon-bedrock-mantle.js"
|
||||
@@ -54,7 +54,6 @@ const route = Route.make({
|
||||
),
|
||||
},
|
||||
stream: AnthropicMessages.protocol.stream,
|
||||
supportsEffortUpdates: AnthropicMessages.protocol.supportsEffortUpdates,
|
||||
}),
|
||||
endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
|
||||
auth: Auth.none,
|
||||
|
||||
@@ -40,7 +40,6 @@ export * as Stability from "./stability.js"
|
||||
export * as TogetherAI from "./togetherai.js"
|
||||
export * as TypeSafeAI from "./typesafe-ai.js"
|
||||
export * as VercelAIGateway from "./vercel-ai-gateway.js"
|
||||
export * as Venice from "./venice.js"
|
||||
export * as XAI from "./xai.js"
|
||||
export * as ZAI from "./zai.js"
|
||||
export * as ZAICodingPlan from "./zai-coding-plan.js"
|
||||
@@ -50,7 +50,7 @@ export const gpt5DefaultOptions = (modelID: string): ProviderOptions | undefined
|
||||
export const openAIDefaultOptions = (modelID: string): ProviderOptions | undefined =>
|
||||
mergeProviderOptions(openAIProviderOptions({ store: false }), gpt5DefaultOptions(modelID))
|
||||
|
||||
export const withOpenAIOptions = <Options extends { readonly providerOptions?: ProviderOptions }>(
|
||||
export const withOpenAIOptions = <Options extends { readonly providerOptions?: OpenAIProviderOptionsInput }>(
|
||||
modelID: string,
|
||||
options: Options,
|
||||
): Omit<Options, "providerOptions"> & { readonly providerOptions?: ProviderOptions } => {
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { VeniceChat } from "../protocols/venice-chat.js"
|
||||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { ProviderID, type ModelID } from "../schema/index.js"
|
||||
|
||||
export const id = ProviderID.make("venice")
|
||||
export type ChatOptionsInput = VeniceChat.OptionsInput
|
||||
export type Config = Omit<RouteDefaultsInput, "providerOptions"> &
|
||||
ProviderAuthOption<"optional"> & {
|
||||
readonly baseURL?: string
|
||||
readonly queryParams?: Readonly<Record<string, string>>
|
||||
readonly providerOptions?: ChatOptionsInput
|
||||
}
|
||||
export type Settings = ProviderPackage.Settings &
|
||||
ChatOptionsInput & {
|
||||
readonly apiKey?: string
|
||||
readonly baseURL?: string
|
||||
readonly queryParams?: Readonly<Record<string, string>>
|
||||
}
|
||||
|
||||
const route = Route.make({
|
||||
id: "venice-chat",
|
||||
provider: id,
|
||||
providerMetadataKey: "venice",
|
||||
protocol: VeniceChat.protocol,
|
||||
endpoint: Endpoint.path("/chat/completions", { baseURL: "https://api.venice.ai/api/v1" }),
|
||||
framing: OpenAIChat.framing,
|
||||
})
|
||||
export const routes = [route]
|
||||
|
||||
export const configure = (input: Config = {}) => {
|
||||
const { apiKey: _apiKey, auth: _auth, baseURL, queryParams, ...rest } = input
|
||||
const chat = (modelID: string | ModelID) =>
|
||||
route
|
||||
.with({
|
||||
...rest,
|
||||
endpoint: { baseURL: baseURL ?? route.endpoint.baseURL, query: queryParams },
|
||||
auth: AuthOptions.bearer(input, "VENICE_API_KEY"),
|
||||
})
|
||||
.model<ChatOptionsInput>({ id: modelID, compatibility: VeniceChat.compatibility })
|
||||
return { id, model: chat, chat, configure }
|
||||
}
|
||||
|
||||
export const provider = configure()
|
||||
export const chat = provider.chat
|
||||
export const model: ProviderPackage.Definition<Settings, ChatOptionsInput>["model"] = (
|
||||
modelID,
|
||||
{ apiKey, baseURL, queryParams, body, headers, ...providerOptions },
|
||||
) =>
|
||||
configure({
|
||||
apiKey,
|
||||
baseURL,
|
||||
queryParams,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body: { ...body } },
|
||||
providerOptions,
|
||||
}).model(modelID)
|
||||
|
||||
export * as Venice from "./venice.js"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import {
|
||||
EvaluationAnswer,
|
||||
EvaluationInput,
|
||||
@@ -8,225 +8,37 @@ import {
|
||||
EvaluationResponse,
|
||||
EvaluationRounding,
|
||||
} from "../experimental/evaluation.js"
|
||||
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
|
||||
import { OpenAIChat } from "../protocols/openai-chat.js"
|
||||
import { OpenResponses } from "../protocols/open-responses.js"
|
||||
import { optionalNull, ProviderShared } from "../protocols/shared.js"
|
||||
import { gatewayProtocol } from "../protocols/utils/gateway-protocol.js"
|
||||
import type { ProviderPackage } from "../provider-package.js"
|
||||
import { Auth } from "../route/auth.js"
|
||||
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
|
||||
import { Route, type RouteDefaultsInput } from "../route/client.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Framing } from "../route/framing.js"
|
||||
import type { Protocol } from "../route/protocol.js"
|
||||
import {
|
||||
AIError,
|
||||
HttpContext,
|
||||
HttpOptions,
|
||||
InvalidProviderOutputError,
|
||||
InvalidRequestError,
|
||||
LLMRequest,
|
||||
ModelID,
|
||||
ProviderID,
|
||||
ProviderMetadata,
|
||||
ReasoningEffort,
|
||||
Usage,
|
||||
} from "../schema/index.js"
|
||||
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js"
|
||||
|
||||
export const id = ProviderID.make("vercel-ai-gateway")
|
||||
const baseURL = "https://ai-gateway.vercel.sh/v1"
|
||||
|
||||
export interface GatewayOptions {
|
||||
/** Service-owned options added by the Gateway without requiring an SDK update. */
|
||||
readonly [key: string]: unknown
|
||||
/** Enables Gateway automatic prompt-cache breakpoint injection (`"auto"`). */
|
||||
readonly caching?: "auto" | (string & {})
|
||||
/** Provider slugs that are the only ones allowed to serve the request (e.g. `["anthropic", "vertex"]`). */
|
||||
readonly only?: ReadonlyArray<string>
|
||||
/** Provider slugs specifying the order in which providers are tried (e.g. `["bedrock", "anthropic"]`). */
|
||||
readonly order?: ReadonlyArray<string>
|
||||
/** Sort candidate providers by cost (`"cost"`), throughput (`"tps"`), or time-to-first-token (`"ttft"`). */
|
||||
readonly sort?: "cost" | "tps" | "ttft" | (string & {})
|
||||
/** Fallback models to try in order, or a conditional `{ model, when }` entry on evaluation requests. */
|
||||
readonly models?: ReadonlyArray<string | Readonly<Record<string, unknown>>>
|
||||
/** Restrict routing to providers with zero data retention agreements. */
|
||||
readonly zeroDataRetention?: boolean
|
||||
/** Restrict routing to providers that do not train on prompt data. */
|
||||
readonly disallowPromptTraining?: boolean
|
||||
/**
|
||||
* Restrict routing to provider models that satisfy every entry: capability
|
||||
* tags (`"implicit-caching"`, `"reasoning"`, `"structured-output"`,
|
||||
* `"tool-use"`, `"vision"`) or weight-format filters (`"quantization:fp8"`,
|
||||
* `"!quantization:fp8"`).
|
||||
*/
|
||||
readonly has?: ReadonlyArray<
|
||||
| "implicit-caching"
|
||||
| "reasoning"
|
||||
| "structured-output"
|
||||
| "tool-use"
|
||||
| "vision"
|
||||
| `quantization:${string}`
|
||||
| `!quantization:${string}`
|
||||
| (string & {})
|
||||
>
|
||||
/** Entity identifier against which Gateway quota is tracked. */
|
||||
readonly quotaEntityId?: string
|
||||
/** Unified service tier intent (`"flex"` or `"priority"`). */
|
||||
readonly serviceTier?: "flex" | "priority" | (string & {})
|
||||
/** End-user identifier for spend tracking and attribution. */
|
||||
readonly user?: string
|
||||
/** User-specified tags for reporting and filtering usage. */
|
||||
readonly tags?: ReadonlyArray<string>
|
||||
/** Request-scoped BYOK credentials keyed by provider slug, used instead of cached workspace credentials. */
|
||||
readonly byok?: Readonly<Record<string, ReadonlyArray<Readonly<Record<string, unknown>>>>>
|
||||
/** Preferred inference region for upstream provider routing. */
|
||||
readonly inferenceRegion?: string
|
||||
/** Per-provider timeouts in milliseconds (e.g. `{ byok: { anthropic: 3000 } }`). */
|
||||
readonly providerTimeouts?: {
|
||||
readonly [key: string]: unknown
|
||||
readonly byok?: Readonly<Record<string, number>>
|
||||
}
|
||||
}
|
||||
|
||||
export type ProviderOptionsInput = OpenResponsesProviderOptionsInput &
|
||||
Omit<AnthropicMessages.OptionsInput, "thinking"> & {
|
||||
/** Reasoning configuration for Messages (`thinking`) or Chat (`reasoning.enabled` + `reasoning.max_tokens`). */
|
||||
readonly thinking?:
|
||||
| AnthropicMessages.OptionsInput["thinking"]
|
||||
| {
|
||||
readonly type: "enabled" | "adaptive" | "disabled" | (string & {})
|
||||
readonly budgetTokens?: number
|
||||
readonly budget_tokens?: number
|
||||
}
|
||||
/** Gateway routing, fallback, BYOK, compliance, and attribution options sent under `body.providerOptions.gateway`. */
|
||||
readonly gateway?: GatewayOptions
|
||||
/** Provider-specific options forwarded under their upstream namespace in `body.providerOptions` (e.g. `{ anthropic: { ... } }`). */
|
||||
readonly upstream?: Readonly<Record<string, Readonly<Record<string, unknown>>>>
|
||||
/** Responses API automatic-cache lifetime (`"5m"` or `"1h"`), sent as top-level `cache_ttl`. */
|
||||
readonly cacheTTL?: "5m" | "1h" | (string & {})
|
||||
/** Responses API count of stable input items to anchor for caching, sent as top-level `cache_anchor_items`. */
|
||||
readonly cacheAnchorItems?: number
|
||||
}
|
||||
|
||||
export interface EvaluationOptions {
|
||||
readonly [key: string]: unknown
|
||||
readonly gateway?: GatewayOptions
|
||||
readonly gateway?: Readonly<{
|
||||
readonly [key: string]: unknown
|
||||
readonly zeroDataRetention?: boolean
|
||||
readonly only?: ReadonlyArray<string>
|
||||
}>
|
||||
}
|
||||
|
||||
export type Options = Omit<RouteDefaultsInput, "providerOptions"> &
|
||||
ProviderAuthOption<"optional"> & {
|
||||
readonly baseURL?: string
|
||||
readonly providerOptions?: ProviderOptionsInput
|
||||
}
|
||||
|
||||
export type Settings = ProviderPackage.Settings & ProviderOptionsInput & { readonly apiKey?: string }
|
||||
|
||||
const GatewayOptionsSchema = Schema.Struct({
|
||||
gateway: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
||||
upstream: Schema.optional(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown))),
|
||||
reasoningEffort: Schema.optional(ReasoningEffort),
|
||||
thinking: Schema.optional(
|
||||
Schema.Struct({
|
||||
type: Schema.String,
|
||||
budgetTokens: Schema.optional(Schema.Number),
|
||||
budget_tokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
),
|
||||
cacheTTL: Schema.optional(Schema.String),
|
||||
cacheAnchorItems: Schema.optional(Schema.Number),
|
||||
})
|
||||
const decodeOptions = ProviderShared.validateWith(Schema.decodeUnknownEffect(GatewayOptionsSchema))
|
||||
|
||||
const prepare = (api: "messages" | "responses" | "chat") =>
|
||||
Effect.fnUntraced(function* (request: LLMRequest) {
|
||||
const options = yield* decodeOptions(request.providerOptions ?? {})
|
||||
const providerOptions = (() => {
|
||||
if (!options.upstream && !options.gateway) return undefined
|
||||
if (!options.gateway) return options.upstream
|
||||
return { ...options.upstream, gateway: options.gateway }
|
||||
})()
|
||||
switch (api) {
|
||||
case "messages": {
|
||||
const effort = options.reasoningEffort
|
||||
if (effort === undefined) return { request, body: { providerOptions } }
|
||||
const enabled = effort !== "none"
|
||||
const thinking = request.providerOptions?.thinking ?? { type: enabled ? "adaptive" : "disabled" }
|
||||
const next = LLMRequest.update(request, {
|
||||
providerOptions: {
|
||||
...request.providerOptions,
|
||||
effort: enabled ? effort : undefined,
|
||||
thinking,
|
||||
},
|
||||
})
|
||||
return { request: next, body: { providerOptions } }
|
||||
}
|
||||
case "responses":
|
||||
return {
|
||||
request,
|
||||
body: {
|
||||
providerOptions,
|
||||
cache_ttl: options.cacheTTL,
|
||||
cache_anchor_items: options.cacheAnchorItems,
|
||||
},
|
||||
}
|
||||
case "chat": {
|
||||
if (!options.thinking) return { request, body: { providerOptions } }
|
||||
const reasoning = {
|
||||
enabled: options.thinking.type !== "disabled",
|
||||
max_tokens: options.thinking.budgetTokens ?? options.thinking.budget_tokens,
|
||||
}
|
||||
return { request, body: { providerOptions, reasoning } }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const route = <Body, Event, State>(input: {
|
||||
readonly id: string
|
||||
readonly protocol: Protocol<Body, string, Event, State>
|
||||
readonly api: "messages" | "responses" | "chat"
|
||||
readonly path: string
|
||||
readonly framing: Framing.Definition<string>
|
||||
readonly defaults?: RouteDefaultsInput
|
||||
}) =>
|
||||
Route.make({
|
||||
id: input.id,
|
||||
provider: id,
|
||||
providerMetadataKey: id,
|
||||
protocol: gatewayProtocol(input.protocol, { id: input.id, prepare: prepare(input.api) }),
|
||||
endpoint: Endpoint.path(input.path, { baseURL }),
|
||||
framing: input.framing,
|
||||
headers: ({ request }): Record<string, string> =>
|
||||
request.promptCacheKey ? { "x-session-affinity": request.promptCacheKey } : {},
|
||||
defaults: input.defaults,
|
||||
})
|
||||
|
||||
const messagesRoute = route({
|
||||
id: "vercel-ai-gateway-messages",
|
||||
protocol: AnthropicMessages.protocol,
|
||||
api: "messages",
|
||||
path: "/messages",
|
||||
framing: AnthropicMessages.framing,
|
||||
defaults: { headers: { "anthropic-version": "2023-06-01" } },
|
||||
})
|
||||
const responsesRoute = route({
|
||||
id: "vercel-ai-gateway-responses",
|
||||
protocol: OpenResponses.protocol,
|
||||
api: "responses",
|
||||
path: "/responses",
|
||||
framing: Framing.sse,
|
||||
defaults: { providerOptions: { store: false, include: ["reasoning.encrypted_content"] } },
|
||||
})
|
||||
const chatRoute = route({
|
||||
id: "vercel-ai-gateway-chat",
|
||||
protocol: OpenAIChat.protocol,
|
||||
api: "chat",
|
||||
path: "/chat/completions",
|
||||
framing: OpenAIChat.framing,
|
||||
})
|
||||
|
||||
export const routes = [messagesRoute, responsesRoute, chatRoute]
|
||||
export type Options = ProviderAuthOption<"optional"> & {
|
||||
readonly baseURL?: string
|
||||
readonly headers?: Record<string, string>
|
||||
readonly http?: HttpOptions.Input
|
||||
}
|
||||
|
||||
const Request = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
@@ -238,43 +50,19 @@ const Request = Schema.StructWithRest(
|
||||
[Schema.Record(Schema.String, Schema.Any)],
|
||||
)
|
||||
const Response = Schema.Struct({
|
||||
model: optionalNull(Schema.String),
|
||||
model: Schema.optional(Schema.String),
|
||||
answers: Schema.Record(Schema.String, EvaluationAnswer),
|
||||
usage: optionalNull(
|
||||
usage: Schema.optional(
|
||||
Schema.Struct({
|
||||
inputTokens: optionalNull(Schema.Number),
|
||||
outputTokens: optionalNull(Schema.Number),
|
||||
inputTokens: Schema.optional(Schema.Number),
|
||||
outputTokens: Schema.optional(Schema.Number),
|
||||
}),
|
||||
),
|
||||
rounding: optionalNull(EvaluationRounding),
|
||||
providerMetadata: optionalNull(ProviderMetadata),
|
||||
rounding: Schema.optional(EvaluationRounding),
|
||||
providerMetadata: Schema.optional(ProviderMetadata),
|
||||
})
|
||||
|
||||
export const configure = (input: Options = {}) => {
|
||||
const { apiKey: _apiKey, auth: _auth, baseURL: endpoint, ...defaults } = input
|
||||
const configured = {
|
||||
...defaults,
|
||||
endpoint: { baseURL: endpoint ?? baseURL },
|
||||
auth: AuthOptions.bearer(input, ["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]),
|
||||
}
|
||||
const messages = (modelID: string | ModelID) =>
|
||||
messagesRoute.with(configured).model<ProviderOptionsInput>({
|
||||
id: modelID,
|
||||
// Recorded Gateway translations for non-Claude models return thinking with empty signatures.
|
||||
compatibility: { requireSignature: modelID.startsWith("anthropic/") },
|
||||
})
|
||||
const responses = (modelID: string | ModelID) =>
|
||||
responsesRoute.with(configured).model<ProviderOptionsInput>({ id: modelID })
|
||||
const chat = (modelID: string | ModelID) =>
|
||||
chatRoute
|
||||
.with(configured)
|
||||
.model<ProviderOptionsInput>({ id: modelID, compatibility: { reasoningField: "reasoning" } })
|
||||
// Each family uses the API whose Gateway translation carries its reasoning state across turns.
|
||||
const model = (modelID: string | ModelID) => {
|
||||
if (/^(openai\/gpt-|spacexai\/grok-)/.test(modelID)) return responses(modelID)
|
||||
if (modelID.startsWith("meta/muse-")) return chat(modelID)
|
||||
return messages(modelID)
|
||||
}
|
||||
const evaluation = (modelID: string | ModelID) =>
|
||||
EvaluationModel.make<EvaluationOptions>({
|
||||
id: modelID,
|
||||
@@ -297,7 +85,9 @@ export const configure = (input: Options = {}) => {
|
||||
(cause) => new AIError({ reason: new InvalidRequestError({ message: cause.message, cause }) }),
|
||||
),
|
||||
)
|
||||
const headers = yield* Auth.toEffect(configured.auth)({
|
||||
const headers = yield* Auth.toEffect(
|
||||
AuthOptions.bearer(input, ["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]),
|
||||
)({
|
||||
request: req,
|
||||
method: "POST",
|
||||
url: url.toString(),
|
||||
@@ -329,54 +119,30 @@ export const configure = (input: Options = {}) => {
|
||||
fail("Vercel AI Gateway returned an invalid evaluation response", cause, text),
|
||||
),
|
||||
)
|
||||
const inputTokens = data.usage?.inputTokens ?? undefined
|
||||
const outputTokens = data.usage?.outputTokens ?? undefined
|
||||
const usage = data.usage
|
||||
? new Usage({
|
||||
inputTokens,
|
||||
outputTokens,
|
||||
totalTokens: ProviderShared.totalTokens(inputTokens, outputTokens, undefined),
|
||||
providerMetadata: { gateway: data.usage },
|
||||
})
|
||||
: undefined
|
||||
return new EvaluationResponse({
|
||||
model: ModelID.make(data.model ?? req.model.id),
|
||||
answers: data.answers,
|
||||
usage,
|
||||
rounding: data.rounding ?? undefined,
|
||||
providerMetadata: data.providerMetadata ?? undefined,
|
||||
usage: data.usage
|
||||
? new Usage({
|
||||
inputTokens: data.usage.inputTokens,
|
||||
outputTokens: data.usage.outputTokens,
|
||||
totalTokens:
|
||||
data.usage.inputTokens === undefined && data.usage.outputTokens === undefined
|
||||
? undefined
|
||||
: (data.usage.inputTokens ?? 0) + (data.usage.outputTokens ?? 0),
|
||||
providerMetadata: { gateway: data.usage },
|
||||
})
|
||||
: undefined,
|
||||
rounding: data.rounding,
|
||||
providerMetadata: data.providerMetadata,
|
||||
})
|
||||
}),
|
||||
},
|
||||
})
|
||||
return { id, model, messages, responses, chat, experimental: { evaluation }, configure }
|
||||
return { id, experimental: { evaluation }, configure }
|
||||
}
|
||||
|
||||
export const provider = configure()
|
||||
export const experimental = provider.experimental
|
||||
export const messages = provider.messages
|
||||
export const responses = provider.responses
|
||||
export const chat = provider.chat
|
||||
|
||||
export const model: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"] = (modelID, settings) =>
|
||||
fromSettings(settings).model(modelID)
|
||||
export const messagesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"] = (modelID, settings) =>
|
||||
fromSettings(settings).messages(modelID)
|
||||
export const responsesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"] = (
|
||||
modelID,
|
||||
settings,
|
||||
) => fromSettings(settings).responses(modelID)
|
||||
export const chatModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"] = (modelID, settings) =>
|
||||
fromSettings(settings).chat(modelID)
|
||||
|
||||
function fromSettings({ apiKey, baseURL, headers, body, ...providerOptions }: Settings) {
|
||||
return configure({
|
||||
apiKey,
|
||||
baseURL,
|
||||
headers,
|
||||
http: body === undefined ? undefined : { body: { ...body } },
|
||||
providerOptions,
|
||||
})
|
||||
}
|
||||
|
||||
export * as VercelAIGateway from "./vercel-ai-gateway.js"
|
||||
@@ -1,2 +0,0 @@
|
||||
export { chatModel as model } from "../vercel-ai-gateway.js"
|
||||
export type { Settings } from "../vercel-ai-gateway.js"
|
||||
@@ -1,2 +0,0 @@
|
||||
export { messagesModel as model } from "../vercel-ai-gateway.js"
|
||||
export type { Settings } from "../vercel-ai-gateway.js"
|
||||
@@ -1,2 +0,0 @@
|
||||
export { responsesModel as model } from "../vercel-ai-gateway.js"
|
||||
export type { Settings } from "../vercel-ai-gateway.js"
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Config, Effect, Option, Redacted } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Headers } from "effect/http"
|
||||
import { AuthenticationError, AIError, type HttpOptions } from "../schema/index.js"
|
||||
|
||||
export class MissingCredentialError extends Error {
|
||||
@@ -95,7 +95,7 @@ export const optional = (secret: Secret | undefined, source = "optional value")
|
||||
export const config = (name: string) =>
|
||||
credential(
|
||||
Effect.gen(function* () {
|
||||
const secret = yield* Config.option(Config.redacted(name))
|
||||
const secret = yield* Config.option(Config.Redacted(name))
|
||||
if (Option.isSome(secret) && Redacted.value(secret.value) !== "") return secret.value
|
||||
return yield* Effect.fail(new MissingCredentialError(name, `${name} is not set`))
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Context, type Effect } from "effect"
|
||||
import type { HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import type { HttpClientRequest, HttpClientResponse } from "effect/http"
|
||||
import type { AIError } from "../schema/errors.js"
|
||||
|
||||
// The service tag lives in its own leaf module so `Media.Asset` (imported by the schema layer) can require the
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
HttpClientError,
|
||||
HttpClientRequest,
|
||||
HttpClientResponse,
|
||||
} from "effect/unstable/http"
|
||||
} from "effect/http"
|
||||
import { HttpContext, HttpRateLimitDetails, AIError, TransportError } from "../schema/index.js"
|
||||
import { classifyProviderFailure, providerErrorMessage } from "../provider-error.js"
|
||||
import { Service, type HttpMiddleware, type Interface } from "./executor-service.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Stream } from "effect"
|
||||
import { makeParser } from "effect/unstable/encoding/Sse"
|
||||
import { makeParser, type Event } from "effect/encoding/Sse"
|
||||
import { AIError, InvalidProviderOutputError } from "../schema/index.js"
|
||||
|
||||
/**
|
||||
@@ -42,39 +42,43 @@ export const sseFraming = (
|
||||
Stream.decodeText(),
|
||||
Stream.mapAccumEffect(
|
||||
() => {
|
||||
const output: string[] = []
|
||||
const output: Event[] = []
|
||||
return {
|
||||
output,
|
||||
parser: makeParser((event) => {
|
||||
if (
|
||||
event._tag === "Event" &&
|
||||
(events === undefined || events.has(event.event)) &&
|
||||
event.data.length > 0 &&
|
||||
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
||||
// `data: null`, between events or after `[DONE]`. No protocol has a
|
||||
// null event, so it carries nothing and must not abort the stream.
|
||||
event.data !== "null" &&
|
||||
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
||||
// keepalive comment as `data: : keepalive` while reasoning.
|
||||
event.data !== ": keepalive" &&
|
||||
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message"))
|
||||
)
|
||||
output.push(event.data)
|
||||
if (event._tag === "Event") output.push(event)
|
||||
}),
|
||||
}
|
||||
},
|
||||
(state, chunk) => {
|
||||
const error = state.parser.feed(chunk)
|
||||
if (!error) return Effect.succeed([state, state.output.splice(0)] as const)
|
||||
const reason = new InvalidProviderOutputError({
|
||||
route: "sse",
|
||||
message: error.message,
|
||||
body: chunk,
|
||||
cause: error,
|
||||
})
|
||||
return Effect.fail(new AIError({ reason }))
|
||||
},
|
||||
(state, chunk) =>
|
||||
Effect.gen(function* () {
|
||||
const error = state.parser.feed(chunk)
|
||||
if (error)
|
||||
return yield* new AIError({
|
||||
reason: new InvalidProviderOutputError({
|
||||
route: "sse",
|
||||
message: error.message,
|
||||
body: chunk,
|
||||
cause: error,
|
||||
}),
|
||||
})
|
||||
return [state, state.output.splice(0)] as const
|
||||
}),
|
||||
),
|
||||
Stream.filter(
|
||||
(event) =>
|
||||
(events === undefined || events.has(event.event)) &&
|
||||
event.data.length > 0 &&
|
||||
// Some OpenAI-compatible proxies serialize an empty flush as a bare
|
||||
// `data: null`, between events or after `[DONE]`. No protocol has a
|
||||
// null event, so it carries nothing and must not abort the stream.
|
||||
event.data !== "null" &&
|
||||
// Vertex AI partner models (e.g. `xai/grok-4.6`) send their SSE
|
||||
// keepalive comment as `data: : keepalive` while reasoning.
|
||||
event.data !== ": keepalive" &&
|
||||
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message")),
|
||||
),
|
||||
Stream.map((event) => event.data),
|
||||
)
|
||||
|
||||
/** Server-Sent Events framing. Used by every JSON-streaming HTTP provider. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Clock, Duration, Effect, Schema, type Stream } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import { HttpClientResponse } from "effect/http"
|
||||
import type { Snapshot, Status } from "../generation.js"
|
||||
import { Media } from "../media.js"
|
||||
import type { AuthInput } from "./auth.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Duration, Effect, Schedule, Schema, Stream } from "effect"
|
||||
import { Headers, HttpClientRequest, type HttpClientResponse } from "effect/unstable/http"
|
||||
import { Headers, HttpClientRequest, type HttpClientResponse } from "effect/http"
|
||||
import { Auth, type AuthInput } from "./auth.js"
|
||||
import { Endpoint } from "./endpoint.js"
|
||||
import { RequestExecutorService, type Interface } from "./executor-service.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Clock, Duration, Effect, Stream } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { Headers, HttpClientRequest } from "effect/http"
|
||||
import { Auth } from "../auth.js"
|
||||
import { render as renderEndpoint } from "../endpoint.js"
|
||||
import { Framing } from "../framing.js"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Effect, Scope, Stream } from "effect"
|
||||
import type { Headers } from "effect/unstable/http"
|
||||
import type { Headers } from "effect/http"
|
||||
import type { AIError, HttpContext } from "../../schema/index.js"
|
||||
|
||||
export interface WebSocketChannelExecutor {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Cause, Effect, Queue, Stream } from "effect"
|
||||
import { Headers } from "effect/unstable/http"
|
||||
import { Socket } from "effect/unstable/socket"
|
||||
import { Headers } from "effect/http"
|
||||
import { Socket } from "effect/socket"
|
||||
import {
|
||||
AIError,
|
||||
AIErrorReason,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Schema } from "effect"
|
||||
import { withStatics } from "@opencode/schema/schema"
|
||||
import { Tool } from "@opencode/schema/tool"
|
||||
import {
|
||||
CacheHint,
|
||||
@@ -28,7 +29,7 @@ export type SystemPart = Schema.Schema.Type<typeof systemPartSchema>
|
||||
|
||||
const makeSystemPart = (text: string): SystemPart => ({ type: "text", text })
|
||||
|
||||
export const SystemPart = Object.assign(systemPartSchema, {
|
||||
export const SystemPart = withStatics(systemPartSchema, {
|
||||
make: makeSystemPart,
|
||||
content: (input?: string | SystemPart | ReadonlyArray<SystemPart>) => {
|
||||
if (input === undefined) return []
|
||||
@@ -76,7 +77,7 @@ const toolResultValueSchema = Schema.Union([
|
||||
export type ToolResultValue = Schema.Schema.Type<typeof toolResultValueSchema>
|
||||
const isToolResultValue = Schema.is(toolResultValueSchema)
|
||||
|
||||
export const ToolResultValue = Object.assign(toolResultValueSchema, {
|
||||
export const ToolResultValue = withStatics(toolResultValueSchema, {
|
||||
is: isToolResultValue,
|
||||
make: (value: unknown, type: ToolResultValue["type"] = "json"): ToolResultValue => {
|
||||
if (isToolResultValue(value)) return value
|
||||
@@ -90,7 +91,7 @@ export interface ToolOutput {
|
||||
readonly content: ReadonlyArray<Tool.Content>
|
||||
}
|
||||
|
||||
export const ToolOutput = Object.assign(
|
||||
export const ToolOutput = withStatics(
|
||||
Schema.Struct({
|
||||
structured: Schema.Unknown,
|
||||
content: Schema.Array(Tool.Content),
|
||||
@@ -127,7 +128,7 @@ const toolResultText = (value: unknown) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const ToolCallPart = Object.assign(
|
||||
export const ToolCallPart = withStatics(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("tool-call"),
|
||||
id: Schema.String,
|
||||
@@ -145,7 +146,7 @@ export const ToolCallPart = Object.assign(
|
||||
)
|
||||
export type ToolCallPart = Schema.Schema.Type<typeof ToolCallPart>
|
||||
|
||||
export const ToolResultPart = Object.assign(
|
||||
export const ToolResultPart = withStatics(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("tool-result"),
|
||||
id: Schema.String,
|
||||
@@ -209,7 +210,7 @@ const compactionPartSchema = Schema.Struct({
|
||||
)
|
||||
.annotate({ identifier: "LLM.Content.Compaction" })
|
||||
export type CompactionPart = typeof compactionPartSchema.Type
|
||||
export const CompactionPart = Object.assign(compactionPartSchema, {
|
||||
export const CompactionPart = withStatics(compactionPartSchema, {
|
||||
make: (input: Omit<CompactionPart, "type" | "encrypted" | "text"> & CompactionContent): CompactionPart =>
|
||||
Schema.decodeUnknownSync(compactionPartSchema)({ type: "compaction", ...input }),
|
||||
})
|
||||
@@ -326,7 +327,7 @@ export type ToolNamespaceEntryInput = ToolNamespaceInput & { readonly type: "nam
|
||||
|
||||
export const ToolNamespace: Schema.Codec<ToolNamespace> & {
|
||||
readonly make: (input: ToolNamespace | ToolNamespaceInput) => ToolNamespace
|
||||
} = Object.assign(
|
||||
} = withStatics(
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("namespace"),
|
||||
name: Schema.String,
|
||||
@@ -346,7 +347,7 @@ export type ToolEntry = ToolDefinition | ToolNamespace
|
||||
export type ToolEntryInput = ToolDefinition.Input | ToolNamespaceEntryInput
|
||||
export const ToolEntry: Schema.Codec<ToolEntry> & {
|
||||
readonly make: (input: ToolEntryInput) => ToolEntry
|
||||
} = Object.assign(
|
||||
} = withStatics(
|
||||
Schema.Union([ToolDefinition, ToolNamespace]).pipe(
|
||||
Schema.toTaggedUnion("type"),
|
||||
Schema.annotate({ identifier: "LLM.ToolEntry" }),
|
||||
|
||||