Compare commits

..

162 Commits

Author SHA1 Message Date
Kit Langton 275b10c843 fix(core): tighten MCP transport shutdown 2026-08-12 12:40:48 -04:00
Kit Langton be4d9b4c38 fix(core): harden MCP transport lifecycle 2026-08-12 12:25:51 -04:00
Kit Langton d715e3568a refactor(core): spawn MCP servers through environment 2026-08-12 12:06:15 -04:00
Matt Robinson f06a86eeac feat(client): support service version ranges (#42023)
Co-authored-by: Dax Raad <d@ironbay.co>
2026-08-12 09:01:37 -07:00
Kit Langton 653b7d79cd fix(tui): restore navigation keybind defaults (#42066) 2026-08-12 11:57:39 -04:00
Kit Langton 70ce0d0970 feat(tui): jump between open menu sections (#42061) 2026-08-12 15:52:51 +00:00
opencode-agent[bot] 0777e84598 fix(tui): fill image message background (#42062)
Co-authored-by: Simon Klee <hello@simonklee.dk>
2026-08-12 15:51:19 +00:00
Kit Langton bef795b2fe fix(tui): smooth session tab marquees (#42055) 2026-08-12 15:49:17 +00:00
Kit Langton 70853b1e5b feat(tui): surface plugin failures (#41940) 2026-08-12 10:51:00 -04:00
opencode-agent[bot] 1fea1c2ebc fix(core): route Muse models to Meta prompt (#42036)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-12 09:31:59 -05:00
opencode-agent[bot] 1da591b84d fix(core): return content-only Code Mode results (#41954)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-12 09:14:41 -05:00
opencode-agent[bot] b990f9a5c1 chore: generate 2026-08-12 13:32:36 +00:00
Dax Raad 9769e7012c feat(core): configure package publishing 2026-08-12 09:30:34 -04:00
opencode-agent[bot] 5fd28cffc5 refactor(tui): use command IDs for v2 keybinds (#41882)
Requested by Sebastian Herrlinger (@kommander). Rebased onto current v2 with conflicts resolved and all required checks passing.
2026-08-12 12:53:24 +00:00
Luke Parker c8dffb6893 test(app): deflake cached tab paint probe (#41965) 2026-08-12 20:21:27 +10:00
opencode-agent[bot] 01cbdcb8e4 fix(ai): batch Anthropic parallel tool results (#41948)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-12 00:18:50 -05:00
opencode-agent[bot] bf751a907d fix(core): jitter session retry delays (#41942)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-11 23:58:20 -05:00
opencode-agent[bot] 9d63ca8f90 chore: generate 2026-08-12 04:19:09 +00:00
opencode-agent[bot] e3bd82013c fix(ai): preserve stream transport failures (#41779)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-08-11 23:17:48 -05:00
Kit Langton 90b6fa0eab fix(core): expose local attachment paths (#41789) 2026-08-11 23:32:49 -04:00
Kit Langton 5b7b1830d2 refactor(server): resume suspended sessions unconditionally in the fetch entry (#41938) 2026-08-12 03:31:30 +00:00
Kit Langton a8fc664b6d fix(tui): pad markdown table cells (#41937) 2026-08-11 23:21:00 -04:00
Kit Langton d853ff8848 fix(tui): configure new session location (#41929) 2026-08-11 22:55:48 -04:00
opencode-agent[bot] 94bc0fc6fa chore: generate 2026-08-12 02:40:33 +00:00
Kit Langton d3eecf7ba2 feat(tui): compact turn token usage with expandable steps (#41922) 2026-08-12 02:39:19 +00:00
Kit Langton 99166f7c17 feat(tui): add plus button to session tab bar (#41887) 2026-08-11 22:38:08 -04:00
opencode-agent[bot] 08dcf7d731 chore: generate 2026-08-12 02:23:16 +00:00
Kit Langton caae28e0d4 fix(tui): render instruction updates as compact notices (#41900) 2026-08-11 22:21:24 -04:00
Kit Langton c83933d1d4 fix(core): gate tool snapshot on initial MCP registration (#41884) 2026-08-11 22:21:21 -04:00
Kit Langton c86f1c41ff fix(tui): show completed write output (#41883) 2026-08-11 22:20:55 -04:00
Kit Langton 5c0cc8e617 fix(tui): align running shell output (#41880) 2026-08-11 22:20:52 -04:00
Kit Langton 1b45061afb feat(tui): experiments via devtools bar, drafts stay put (#41917) 2026-08-12 02:08:06 +00:00
opencode-agent[bot] 07bcd290c2 chore: generate 2026-08-12 02:06:08 +00:00
Luke Parker 04ad06e2e3 fix(desktop): align local development identity (#41889) 2026-08-12 12:04:57 +10:00
Dax 93965df860 feat(session): record location switches (#41899) 2026-08-11 19:03:57 -07:00
Kit Langton f0333e0eea chore(tui): remove leftover discovery smoke plugin (#41897) 2026-08-11 21:56:55 -04:00
Kit Langton 452335a78d fix(tui): truncate fractional mtimes in fresh plugin specifiers (#41891) 2026-08-11 21:56:44 -04:00
Kit Langton 9322f5d2c9 fix(client): surface managed startup stderr (#41793) 2026-08-11 21:55:43 -04:00
opencode-agent[bot] d6ed520c25 chore: generate 2026-08-12 01:38:26 +00:00
Kit Langton 96a74ffcc6 chore(core): drop obsolete StreamSse hunk from effect patch (#41892) 2026-08-11 21:37:09 -04:00
Kit Langton c858986b08 feat(server): web-standard fetch handler entry (#41896) 2026-08-11 21:37:06 -04:00
Dax Raad f6611a1f56 refactor(core): internalize effect sqlite adapter 2026-08-11 21:33:23 -04:00
Kit Langton 57b636df00 test(tui): resolve autocomplete paths per platform (#41893) 2026-08-11 21:28:23 -04:00
opencode-agent[bot] 3489abedc0 chore: generate 2026-08-12 01:12:18 +00:00
Dax Raad 49a4175a34 fix: make workspace imports NodeNext compatible 2026-08-11 21:09:46 -04:00
Dax Raad b50b8268f2 feat(codemode): configure package publishing 2026-08-11 21:09:46 -04:00
Dax Raad 51512862a5 feat: add V2 curl installer 2026-08-11 21:03:15 -04:00
Kit Langton 3d23c907eb fix(core): restore bundler resolution for source-imported deps (#41885) 2026-08-11 21:01:24 -04:00
opencode-agent[bot] 9c4e6b500e chore: generate 2026-08-12 00:58:51 +00:00
Dax 5da7eaa6eb feat(api): continue pending work after interrupt (#41888) 2026-08-11 17:56:54 -07:00
Kit Langton c254ba8a7f core: embed models.dev snapshot instead of compile-time define (#41838) 2026-08-11 20:55:09 -04:00
Kit Langton d8e126b817 feat(tui): hidden experiments section with per-tab prompt drafts (#41862) 2026-08-11 20:52:56 -04:00
James Long 7987aed8f3 feat(tui): autocomplete cd directories (#41870) 2026-08-11 20:52:16 -04:00
Kit Langton 0df3070d6d test(client): accelerate service lifecycle tests (#41879) 2026-08-11 20:50:25 -04:00
Luke Parker c217ebe2ad fix(desktop): skip web ui build in dev (#41881) 2026-08-12 10:25:32 +10:00
Dax Raad 4acdeffbe9 refactor(core): require explicit import extensions 2026-08-11 20:22:50 -04:00
Kit Langton dc82a446b9 fix(core): guard Deferred waiter cleanup in vendored effect patch (#41858) 2026-08-11 20:16:21 -04:00
Luke Parker c4bea9d558 fix(app): stabilize markdown worker startup (#41487) 2026-08-12 10:05:32 +10:00
Luke Parker 1190ef3818 feat(desktop): support local server builds (#41486) 2026-08-12 09:56:47 +10:00
opencode-agent[bot] 055a380e66 fix(core): parameterize v1 migration messages (#41877)
Co-authored-by: Dax <826656+thdxr@users.noreply.github.com>
2026-08-11 19:51:37 -04:00
Dax Raad 456c26a012 feat(tui): show localhost on pair screen 2026-08-11 19:49:33 -04:00
opencode-agent[bot] 6072fc5c1b chore: generate 2026-08-11 22:44:47 +00:00
Brendan Allan 20df2fdba6 feat(cli): embed web ui (#41525)
Co-authored-by: Dax Raad <d@ironbay.co>
2026-08-11 15:43:07 -07:00
opencode-agent[bot] f1399dcb65 fix(desktop): orchestrate update restarts (#41865)
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
2026-08-12 08:38:18 +10:00
Dax Raad 3507bd10b6 fix(www): match OG images to docs theme 2026-08-11 18:28:51 -04:00
Dax Raad 492ae1fdfa feat(www): match legacy docs theme 2026-08-11 18:20:58 -04:00
Kit Langton b00d8d65fe feat(tui): hierarchical slot tree for plugin UI placement (#41189) 2026-08-11 22:00:04 +00:00
Kit Langton f1366d80c8 fix(core): default #sqlite resolution to the node driver (#41834) 2026-08-11 17:50:09 -04:00
opencode-agent[bot] 549a8f826b fix(core): log Plan reminder failures (#41856)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2026-08-11 16:39:26 -05:00
Kit Langton 59970699d0 test(core): narrow plugin test layer (#41852) 2026-08-11 17:23:47 -04:00
Aiden Cline b35c5fc985 fix(core): detect copilot PDF input support (#41854) 2026-08-11 16:05:36 -05:00
Kit Langton 627e67323c docs: remove ideal-pseudocode project skill (#41851) 2026-08-11 17:03:05 -04:00
opencode-agent[bot] b97d964e5c chore: generate 2026-08-11 20:53:50 +00:00
Aiden Cline 3fd3e28690 fix(core): classify copilot utility requests (#41840) 2026-08-11 15:51:55 -05:00
Kit Langton b4abeb4788 test(core): narrow effect flock harness (#41837) 2026-08-11 16:51:42 -04:00
Kit Langton 14deb6baf7 docs: clarify skill source precedence (#41844) 2026-08-11 20:46:14 +00:00
Aiden Cline ab6e18e4ff fix(core): route Vertex Anthropic natively (#41836) 2026-08-11 15:29:02 -05:00
Kit Langton 2b6dd2559c fix(core): prefer nearest skill source (#41788) 2026-08-11 16:13:32 -04:00
Kit Langton 2b7bd84867 test(core): speed up subagent tool suite (#41835) 2026-08-11 16:13:04 -04:00
Kit Langton baa54a5150 test(core): speed up shell tool suite (#41831) 2026-08-11 16:03:50 -04:00
Kit Langton c5704d3e3b feat(core): sqlite driver for durable object storage (#41659) 2026-08-11 15:45:23 -04:00
Kit Langton e3336725db fix(core): normalize provider endpoint templates (#41816) 2026-08-11 15:42:54 -04:00
opencode-agent[bot] ff3ecefd24 fix(cli): sign macOS preview binaries (#40662)
Co-authored-by: Ryan Vogel <89211796+R44VC0RP@users.noreply.github.com>
2026-08-11 15:37:44 -04:00
Kit Langton 8486bbcdc1 refactor(core): unify fff runtime adapters (#41827) 2026-08-11 15:22:03 -04:00
Kit Langton 2621dde1c9 refactor(core): unify config collection decoding (#41826) 2026-08-11 15:21:52 -04:00
Kit Langton a253c0437e test(core): await shell tool registration (#41825) 2026-08-11 15:21:35 -04:00
opencode-agent[bot] d8b3e528e8 fix(core): use standard web search key dialogs (#41821)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-11 14:13:58 -05:00
Aiden Cline a5d6969f6f feat(core): extract plan agent into a plugin (#41665) 2026-08-11 13:49:24 -05:00
opencode-agent[bot] 3954d7979d chore: generate 2026-08-11 18:11:13 +00:00
Kit Langton a69a372f27 fix(util): defer module-scope randomness and import.meta path derivation (#41765) 2026-08-11 14:09:18 -04:00
Kit Langton 7300e7e10f core: write-ahead execution claims replace shutdown-hook suspension (#41800) 2026-08-11 14:09:04 -04:00
James Long eeb870b0cc feat(sdk): configure embedded logging (#41809) 2026-08-11 14:03:55 -04:00
Kit Langton 136bad9f17 feat(core): discover AGENTS.md up to the home directory (#41652) 2026-08-11 13:57:10 -04:00
Kit Langton 17536a9237 fix(core): discover local plugin packages (#41784) 2026-08-11 13:14:46 -04:00
Kit Langton 315bc6ac2e fix(acp): avoid implicit model variant (#41782) 2026-08-11 13:09:59 -04:00
Kit Langton a183fb5615 refactor(core): share SQLite client adapter (#41797) 2026-08-11 13:07:22 -04:00
Kit Langton 2c1596ca80 refactor(core): share AI SDK provider factory (#41796) 2026-08-11 13:07:14 -04:00
Kit Langton 9e082c2d43 refactor(core): centralize project upsert (#41795) 2026-08-11 13:07:05 -04:00
Kit Langton fa5ca85e30 refactor(core): reuse plugin source discovery (#41794) 2026-08-11 13:06:58 -04:00
Kit Langton 37a8c6c916 fix(ai): merge Bedrock tool result messages (#41780) 2026-08-11 13:03:31 -04:00
Kit Langton 23b0688a7f fix(server): await models before listing (#41783) 2026-08-11 12:18:07 -04:00
opencode-agent[bot] d0dd49bd84 chore: generate 2026-08-11 16:12:58 +00:00
Kit Langton db9a3b6c41 refactor(core): compact question tool schema (#41772) 2026-08-11 12:09:37 -04:00
opencode-agent[bot] 961b51b509 fix(core): yield while clearing migration events (#41775)
Co-authored-by: Dax Raad <d@ironbay.co>
2026-08-11 16:02:30 +00:00
opencode-agent[bot] 964f7f4254 chore: generate 2026-08-11 15:53:52 +00:00
Aiden Cline 8c27c8485e feat(session): persist previous selections (#41771) 2026-08-11 10:52:14 -05:00
opencode-agent[bot] 6721ff5328 fix(core): omit deprecated models.dev models (#41769)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-11 10:17:04 -05:00
Kit Langton 026e0c634f refactor(core): reuse plugin directory names (#41754) 2026-08-11 10:40:36 -04:00
Kit Langton c581b59b7f refactor(merman): simplify spatial span assembly (#41757) 2026-08-11 10:40:22 -04:00
Kit Langton 5cc7811ec2 refactor(core): defer database global lookup (#41755) 2026-08-11 10:40:03 -04:00
Kit Langton 5d32845b02 refactor(tui): simplify marquee reset (#41758) 2026-08-11 10:39:51 -04:00
Kit Langton e9f5842f29 refactor: simplify attachment identity tracking (#41756) 2026-08-11 10:39:42 -04:00
Kit Langton 7b9734593a refactor(core): generate static imports for the migration manifest (#41657) 2026-08-11 10:35:19 -04:00
opencode-agent[bot] 1dbfc7cfab chore: generate 2026-08-11 14:12:14 +00:00
Kit Langton 3441b95afc fix(core): models.dev catalog population must survive KV cache write failures (#41735) 2026-08-11 10:09:37 -04:00
opencode-agent[bot] 306204bad8 fix(app): handle untitled session tab info (#41700)
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
2026-08-11 18:02:10 +10:00
Aiden Cline 47c8d85904 feat(plugin): allow tool hooks to fail with tool errors (#41668) 2026-08-11 00:36:59 -05:00
Aiden Cline c401076b6f fix(core): preserve AI SDK tool media (#41672) 2026-08-11 00:33:33 -05:00
Luke Parker 1aef4de853 chore(desktop): skip unused beta CLI builds (#41673) 2026-08-11 15:07:21 +10:00
opencode-agent[bot] 9c94634515 fix(tui): use active model for compaction (#41608)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
2026-08-10 23:50:51 -05:00
Luke Parker c2b754bb03 feat(desktop): publish v2 beta desktop (#41626) 2026-08-11 14:33:31 +10:00
Aiden Cline 2372edd5eb feat(tui): show previous agent in switch notices (#41661) 2026-08-10 23:09:26 -05:00
Kit Langton a5f7f8d3b5 fix(tui): deduplicate repeated image attachments (#41651) 2026-08-10 23:39:38 -04:00
Aiden Cline 4df276b9e8 feat(session): persist previous agent on switch (#41621) 2026-08-10 22:35:16 -05:00
Kit Langton 518af92c5b refactor(core): move the models.dev catalog cache from disk to KV (#41649) 2026-08-10 22:40:41 -04:00
Kit Langton 5d8c48718b refactor(core): move instruction discovery to the config side (#41629) 2026-08-10 22:32:58 -04:00
Kit Langton 41c5853739 refactor: route Global path consumers through the service (#41632) 2026-08-10 21:37:09 -04:00
Kit Langton 8d989f6829 fix(tui): collapse execute child details (#41624) 2026-08-10 21:20:51 -04:00
Kit Langton 753fa4cd60 fix(core): isolate config plugin tests from ambient user config (#41631) 2026-08-11 01:16:08 +00:00
opencode-agent[bot] d99a268ea5 chore: generate 2026-08-11 00:39:33 +00:00
Kit Langton 1113adfd5e refactor(core): skill service stores values, config plugin owns the filesystem (#41622) 2026-08-10 20:38:08 -04:00
Kit Langton 6afff5a55f fix(util): no filesystem side effects at global module load (#41619) 2026-08-10 20:38:04 -04:00
Kit Langton 71f5e4189d refactor(core): move plugin discovery and watching to the config side (#41618) 2026-08-10 20:15:08 -04:00
Kit Langton b49bad9a86 fix(merman): remove sequence lifeline fade (#41623) 2026-08-10 19:48:28 -04:00
Kit Langton 2580f880a8 feat(merman): refine sequence diagram styling (#41617) 2026-08-10 19:12:46 -04:00
Kit Langton 9d34029cd9 fix(core): runtime-neutral legacy credential import (#41607) 2026-08-10 18:35:52 -04:00
opencode-agent[bot] 33296e7959 test(app): make offset observer scheduling deterministic (#41602)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-08-10 17:24:05 -05:00
Simon Klee 283258e95b feat(tui): add clipboard image previews and transcript rendering (#41603)
Use the OpenTUI clipboard service for image input, show image previews in
the prompt, and render transcript images with interactive previews.

Note this includes upgrade of opentui to 0.5.1 +
anomalyco/opentui#1271
2026-08-10 22:51:39 +02:00
opencode-agent[bot] d7a7256bb6 test: stabilize Windows CI timing (#41600)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2026-08-10 15:25:55 -05:00
Aiden Cline eec55fa5f8 fix(tui): keep model variant across new session (#41591) 2026-08-10 15:13:23 -05:00
Aiden Cline 7ff27ca8cf fix(core): resolve provider URL variables at runtime (#41580) 2026-08-10 15:03:47 -05:00
Aiden Cline b62dc4a636 fix(tui): show empty state when a flat picker has no matches (#41585) 2026-08-10 14:26:29 -05:00
opencode-agent[bot] ceec9f5b66 fix(tui): measure complete turn duration (#41508)
Co-authored-by: Simon Klee <hello@simonklee.dk>
2026-08-10 20:27:22 +02:00
Kit Langton bbb1b5e7d0 fix(tui): delay background work hint (#41577) 2026-08-10 13:47:31 -04:00
Kit Langton f0b8ad1242 feat(tui): marquee hovered tab titles (#41566) 2026-08-10 13:47:21 -04:00
opencode-agent[bot] be53e3bd81 chore: generate 2026-08-10 17:00:23 +00:00
Dax Raad c22942c1f3 fix(core): tolerate unavailable wellknown config 2026-08-10 12:57:41 -04:00
opencode-agent[bot] 6895728add fix(tui): support single-color themes (#41572) 2026-08-10 12:54:37 -04:00
Aiden Cline 16aad9e6ad fix(core): derive fallback message for empty AI SDK provider errors (#41450) 2026-08-10 11:19:44 -05:00
opencode-agent[bot] 9ab3029947 chore: generate 2026-08-10 15:25:02 +00:00
Kit Langton 3c9f857bf1 fix(tui): sync Mermaid renderer fixes (#41347) 2026-08-10 11:23:10 -04:00
Shoubhit Dash 5e16a5dc66 fix(tui): restore web search failure details (#41545) 2026-08-10 19:24:59 +05:30
Brendan Allan c7852ef0fd refactor(app): establish v2 session controller (#39233) 2026-08-10 08:50:24 +00:00
Brendan Allan 60cd82aec8 refactor(app): extract session timeline controller (#39232) 2026-08-10 15:49:24 +08:00
Brendan Allan c29968bf08 refactor(app): extract provider connection controller (#39230) 2026-08-10 07:20:57 +00:00
Brendan Allan b5b87deaa2 refactor(app): split server management controllers (#39229) 2026-08-10 06:16:06 +00:00
opencode-agent[bot] 5053c1bfdd chore: generate 2026-08-10 05:55:03 +00:00
Luke Parker d97aca139f fix(cli): keep OTLP failures best effort (#41479) 2026-08-10 15:53:52 +10:00
opencode-agent[bot] b2f0f45c9e chore: generate 2026-08-10 04:23:14 +00:00
Aiden Cline f64b024f46 fix(core): resolve models.dev URL env vars (#41474) 2026-08-09 23:22:01 -05:00
opencode-agent[bot] ec11d6ed03 chore: generate 2026-08-10 03:37:40 +00:00
opencode-agent[bot] 0dcedc199c chore: merge dev into v2 (#41460)
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
2026-08-10 03:36:24 +00:00
1368 changed files with 99536 additions and 15703 deletions
+1
View File
@@ -1,3 +1,4 @@
packages/core/migration/**/snapshot.json linguist-generated
packages/core/src/database/migration.gen.ts linguist-generated
packages/core/src/models-dev/snapshot.txt linguist-generated
packages/core/src/**/*.txt text eol=lf
+71 -17
View File
@@ -75,7 +75,7 @@ jobs:
build-cli:
needs: version
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.repository == 'anomalyco/opencode'
if: github.repository == 'anomalyco/opencode' && github.ref_name != 'beta'
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
with:
@@ -91,7 +91,7 @@ jobs:
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
- name: Build legacy CLI
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
run: ./packages/opencode/script/build.ts ${{ (github.ref_name == 'beta' && '--sourcemaps') || '' }}
env:
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
@@ -109,7 +109,7 @@ jobs:
GH_TOKEN: ${{ steps.committer.outputs.token }}
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
with:
name: opencode-cli
path: |
@@ -117,22 +117,76 @@ jobs:
packages/opencode/dist/opencode-linux*
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
with:
name: opencode-cli-windows
path: packages/opencode/dist/opencode-windows*
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: opencode-preview-cli
name: opencode-preview-cli-unsigned
path: packages/cli/dist/cli-*
outputs:
version: ${{ needs.version.outputs.version }}
sign-cli-macos:
needs: build-cli
runs-on: macos-26
if: github.repository == 'anomalyco/opencode'
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0
with:
keychain: build
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: opencode-preview-cli-unsigned
path: packages/cli/dist
- name: Sign macOS CLI binaries
run: |
identity=$(security find-identity -v -p codesigning build.keychain | sed -n 's/.*"\(Developer ID Application:.*\)"/\1/p' | head -n 1)
if [ -z "$identity" ]; then
echo "Developer ID Application identity not found"
exit 1
fi
found=0
for file in packages/cli/dist/cli-darwin-*/bin/opencode2; do
if [ ! -f "$file" ]; then
continue
fi
found=1
codesign \
--force \
--timestamp \
--options runtime \
--entitlements packages/cli/script/entitlements.plist \
--sign "$identity" \
"$file"
codesign --verify --deep --strict --verbose=4 "$file"
codesign --display --requirements - "$file"
done
if [ "$found" -eq 0 ]; then
echo "No macOS CLI binaries found"
exit 1
fi
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: opencode-preview-cli
path: packages/cli/dist/cli-*
if-no-files-found: error
build-node-cli:
needs: version
if: github.repository == 'anomalyco/opencode'
if: github.repository == 'anomalyco/opencode' && github.ref_name != 'beta'
strategy:
fail-fast: false
matrix:
@@ -184,7 +238,7 @@ jobs:
- build-cli
- version
runs-on: blacksmith-4vcpu-windows-2025
if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2'
if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2' && github.ref_name != 'beta'
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
@@ -281,7 +335,6 @@ jobs:
build-electron:
needs:
- build-cli
- version
if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2'
continue-on-error: false
@@ -378,16 +431,14 @@ jobs:
env:
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }}
OPENCODE_CLI_ARTIFACT: ${{ (runner.os == 'Windows' && 'opencode-cli-windows') || 'opencode-cli' }}
RUST_TARGET: ${{ matrix.settings.target }}
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}
OPENCODE_CLI_TARGET: ${{ matrix.settings.target }}
- name: Build
run: bun run build
working-directory: packages/desktop
env:
NODE_OPTIONS: --max-old-space-size=4096
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
@@ -396,6 +447,7 @@ jobs:
VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }}
VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }}
VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }}
OPENCODE_CLI_TARGET: ${{ matrix.settings.target }}
- name: Package
if: needs.version.outputs.release
@@ -405,8 +457,7 @@ jobs:
env:
OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }}
GH_TOKEN: ${{ steps.committer.outputs.token }}
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
CSC_KEYCHAIN: build.keychain
APPLE_API_KEY: ${{ runner.temp }}/apple-api-key.p8
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
@@ -471,6 +522,7 @@ jobs:
needs:
- version
- build-cli
- sign-cli-macos
- build-node-cli
- sign-cli-windows
- build-electron
@@ -500,29 +552,31 @@ jobs:
registry-url: "https://registry.npmjs.org"
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
with:
name: opencode-cli
path: packages/opencode/dist
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
with:
name: opencode-cli-windows
path: packages/opencode/dist
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
if: github.ref_name != 'v2'
if: github.ref_name != 'v2' && github.ref_name != 'beta'
with:
name: opencode-cli-signed-windows
path: packages/opencode/dist
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
if: github.ref_name != 'beta'
with:
name: opencode-preview-cli
path: packages/cli/dist
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
if: github.ref_name != 'beta'
with:
pattern: opencode-node-cli-*
path: packages/cli/dist/node
-13
View File
@@ -1,13 +0,0 @@
import type { Context } from "../../../packages/plugin/src/tui/context"
export default {
id: "test.tui-discovery-smoke",
setup(_context: Context) {
// context.ui.toast.show({
// title: "TUI plugin discovery works",
// message: "Loaded .opencode/plugins/tui/discovery-smoke.ts",
// variant: "success",
// duration: 30_000,
// })
},
}
@@ -1,68 +0,0 @@
---
name: ideal-pseudocode
description: Function-by-function refactoring loop driven by ideal pseudocode. Use when the user says "ideal pseudocode", asks to make a function read like its pseudocode, or wants a dense module cleaned up one function at a time.
---
# Ideal Pseudocode
Clean up one function at a time by writing the pseudocode it _should_ read as, naming every delta between that and the real code, and closing only the gaps the user approves.
## Loop
One function per round. Never touch code before the user picks a direction.
1. **Pick the target** with the user — usually the next function up or down the call chain from the last round.
2. **Read the current code** fresh from disk. It may have unsaved or parallel edits; ask before overwriting anything unexpected.
3. **Distill.** Write the function's ideal pseudocode in a `ts`-fenced code block — TypeScript-flavored for syntax highlighting, but pseudocode: comments over mechanics, one line per idea, every arm of a loop visible as an arm. For a dense or unfamiliar function, first show the _current_ structure as pseudocode, then the ideal.
4. **Name the deltas.** A numbered list; each delta is one concrete gap: control flow smuggled through combinators, a flag-typed parameter, colliding names, side-effect plumbing drowning a loop body, twin functions differing only by a filter. For each, give an honest cost/benefit and a decisive recommendation — including "leave it" when the density has reasons (state the reasons).
5. **Verify before proposing.** Any API the proposal builds on (a combinator, schedule, matcher) gets checked against the installed version's source, not memory.
6. **Get buy-in, then apply.** Minimal edits. Quarantine irreducible ugliness inside a small helper whose name is the pseudocode line it implements. Collapse shallow sibling functions into one deep function only when the distinguishing argument is a domain noun, not a behavior switch.
7. **Validate.** Typecheck and the focused test suites from the package directory; rerun timing-sensitive tests repeatedly. Flag any semantic change the restructure introduced, even when tests pass.
8. **Offer the next target** and stop.
## Style
- Keep each round tight: pseudocode block, deltas, recommendation, one question.
- State mutation belongs in one visible place (usually the loop tail), never spread across error channels or callback closures.
- Prefer early return and `if` chains for control flow; matchers are for producing values.
- Compare names against the question each caller is actually asking; rename toward the domain noun.
## Example round
Every round should read like this (abridged from a real one, on an Effect step-runner):
> `runStep` it is. The ideal pseudocode:
>
> ```ts
> // One logical step: one settled model call, however many attempts it takes.
> // An attempt can end without settling in two ways:
> // transient provider failure -> retry the same call, same assistant message
> // compaction rewrote history -> rebuild the request and call again
> function runStep(session, promotable, step) {
> while (true) {
> const result = callModel(session, promotable, step)
>
> if (result.completed) return result
>
> if (result.retryable) {
> wait(retrySchedule) // exhausted -> publish Step.Failed, fail drain
> promotable = none // never re-promote on a second attempt
> continue
> }
>
> // compaction restarted the step: fresh request from rewritten history
> promotable = none
> step = result.step
> }
> }
> ```
>
> Comparing against the real thing, three deltas:
>
> 1. **The retry arm doesn't live in the loop.** In the pseudocode, retry is just another loop arm. In the real code it's smuggled through the error channel: `Effect.tapError` mutating loop variables via `Effect.sync` closures, then `Effect.retryOrElse` re-running a suspended call. Four mutable variables mutated from three different places — the state flow is invisible unless you already know the trick.
> 2. **`recoverOverflow: typeof compaction.compact | undefined`** — a function-typed parameter used as a one-shot armed/disarmed flag. The callee already closes over `compaction`; a boolean says what it is.
> 3. **`assistantMessageID`** exists solely to resume the same durable message across retries — fine, but only legible once the retry arm is visible in the loop.
>
> The unifying move for (1): a schedule driver, so a retryable failure becomes a caught value handled in the loop body exactly like the compaction arm. One honest trade: it's more manual than the blessed combinator — but the manual version is the loop the combinator was hiding, and the loop already exists for restarts. Two restart mechanisms, one control structure.
>
> Want me to apply it — unified loop, simplified schedule input, boolean `recoverOverflow`?
@@ -0,0 +1,63 @@
---
name: rtl-aware-development
description: OpenCode Desktop should be RTL-aware. Use when implementing or reviewing RTL/LTR behavior in the web app, desktop app, CSS, menus, scrolling, resizing, icons, mixed-direction text, or Electron title bars.
---
# RTL-Aware Development
Treat direction as independent from language. Test English in both directions as well as real RTL and mixed-script content.
## Guidelines
- Set `lang` and `dir` on the document, and propagate direction through component providers used by portaled menus and popovers. Do not change the selected locale merely to force RTL.
- Keep DOM and focus order semantic. Flexbox and Grid already follow `dir`; do not add `row-reverse`, CSS `order`, or reversed markup just to mirror a layout.
- Prefer logical CSS for semantic layout. Reserve physical coordinates for pointer positions, canvas geometry, native window controls, and other genuinely physical placement.
```css
/* Avoid */
padding-left: 12px;
right: 0;
border-right: 1px solid;
text-align: left;
/* Prefer */
padding-inline-start: 12px;
inset-inline-end: 0;
border-inline-end: 1px solid;
text-align: start;
```
- Isolate mixed-direction text. Use `dir="auto"` or `<bdi>` for unknown text; keep code, URLs, IDs, and filesystem paths LTR without forcing the surrounding component LTR.
```html
<span class="file-row"><bdi dir="auto">README.md</bdi></span> <bdi dir="ltr"><code>C:\src\app.ts</code></bdi>
```
- Mirror directional meaning, not every image. Back/forward, previous/next, disclosure, indentation, and directional progress may need mirroring. Do not mirror brands, clocks, media controls, charts, or text. Reverse physical gradients, `translateX`, SVG transforms, and animation deltas explicitly.
- Map interactions through direction. `clientX` remains physical; resizing a logical edge needs an RTL-aware delta. Logical previous/next keyboard controls may swap ArrowLeft/ArrowRight. Follow the relevant WAI-ARIA widget pattern.
- Do not assume LTR scrolling. RTL `scrollLeft` can start at `0` and become negative. Prefer `scrollIntoView({ inline: "nearest" })` or a tested direction-normalizing helper.
- For Electron title bars, prefer native caption controls and use `titleBarOverlay` plus `env(titlebar-area-*)` for the safe content rectangle. Keep Windows/macOS native-control avoidance and `trafficLightPosition` physical; keep app navigation inside that rectangle logical. Mark interactive titlebar children `app-region: no-drag`.
- Verify behavior, not screenshots alone. Check computed styles, pseudo-element geometry, hit zones, focus order, keyboard behavior, submenu direction, zoom/scaling, and both LTR and RTL scroll endpoints.
## Test Matrix
- English + LTR
- English + forced RTL
- A real RTL locale + RTL
- Mixed RTL/LTR content, long labels, numbers, code, and paths
- Keyboard, pointer resize, scrolling, menus/submenus, and Electron titlebar controls in both directions
## References
- [RTL Styling 101, Ahmad Shadeed](https://rtlstyling.com/posts/rtl-styling/)
- [CSS-Tricks: RTL Styling 101](https://css-tricks.com/rtl-styling-101/)
- [CSS-Tricks: CSS Logical Properties and Values](https://css-tricks.com/css-logical-properties-and-values/)
- [W3C: Structural markup and right-to-left text](https://www.w3.org/International/questions/qa-html-dir)
- [W3C: Inline bidirectional markup](https://www.w3.org/International/articles/inline-bidi-markup/)
- [MDN: CSS logical properties and values](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Logical_properties_and_values)
- [MDN: `dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/dir)
- [MDN: `scrollLeft`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
- [web.dev: Logical properties](https://web.dev/learn/css/logical-properties/)
- [Electron: Custom title bar](https://www.electronjs.org/docs/latest/tutorial/custom-title-bar)
- [WAI-ARIA: Window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/)
- [Kobalte: I18n Provider](https://kobalte.dev/docs/core/components/i18n-provider/)
-27
View File
@@ -252,33 +252,6 @@ These are not strictly enforced, they are just general guidelines:
For net-new functionality, start with a design conversation. Open an issue describing the problem, your proposed approach (optional), and why it belongs in OpenCode. The core team will help decide whether it should move forward; please wait for that approval instead of opening a feature PR directly.
## Trust & Vouch System
This project uses [vouch](https://github.com/mitchellh/vouch) to manage contributor trust. The vouch list is maintained in [`.github/VOUCHED.td`](.github/VOUCHED.td).
### How it works
- **Vouched users** are explicitly trusted contributors.
- **Denounced users** are explicitly blocked. Issues and pull requests from denounced users are automatically closed. If you have been denounced, you can request to be unvouched by reaching out to a maintainer on [Discord](https://opencode.ai/discord)
- **Everyone else** can participate normally — you don't need to be vouched to open issues or PRs.
### For maintainers
Collaborators with write access can manage the vouch list by commenting on any issue:
- `vouch` — vouch for the issue author
- `vouch @username` — vouch for a specific user
- `denounce` — denounce the issue author
- `denounce @username` — denounce a specific user
- `denounce @username <reason>` — denounce with a reason
- `unvouch` / `unvouch @username` — remove someone from the list
Changes are committed automatically to `.github/VOUCHED.td`.
### Denouncement policy
Denouncement is reserved for users who repeatedly submit low-quality AI-generated contributions, spam, or otherwise act in bad faith. It is not used for disagreements or honest mistakes.
## Issue Requirements
All issues **must** use one of our issue templates:
+75 -121
View File
@@ -53,7 +53,7 @@
},
"packages/app": {
"name": "@opencode-ai/app",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@corvu/drawer": "catalog:",
"@dnd-kit/abstract": "0.5.0",
@@ -220,7 +220,7 @@
},
"packages/console/app": {
"name": "@opencode-ai/console-app",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@ibm/plex": "6.4.1",
@@ -256,7 +256,7 @@
},
"packages/console/core": {
"name": "@opencode-ai/console-core",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"@jsx-email/render": "1.1.1",
@@ -283,7 +283,7 @@
},
"packages/console/function": {
"name": "@opencode-ai/console-function",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@openauthjs/openauth": "0.0.0-20250322224806",
"@opencode-ai/console-core": "workspace:*",
@@ -300,7 +300,7 @@
},
"packages/console/mail": {
"name": "@opencode-ai/console-mail",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
@@ -324,7 +324,7 @@
},
"packages/console/support": {
"name": "@opencode-ai/console-support",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@opencode-ai/console-core": "workspace:*",
@@ -345,9 +345,6 @@
"packages/core": {
"name": "@opencode-ai/core",
"version": "1.18.4",
"bin": {
"opencode": "./bin/opencode",
},
"dependencies": {
"@ai-sdk/alibaba": "1.0.17",
"@ai-sdk/amazon-bedrock": "4.0.112",
@@ -367,15 +364,12 @@
"@ai-sdk/togetherai": "2.0.41",
"@ai-sdk/vercel": "2.0.39",
"@aws-sdk/credential-providers": "3.1057.0",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@ff-labs/fff-bun": "0.10.1",
"@ff-labs/fff-node": "0.10.1",
"@lydell/node-pty": "catalog:",
"@modelcontextprotocol/sdk": "1.29.0",
"@opencode-ai/ai": "workspace:*",
"@opencode-ai/codemode": "workspace:*",
"@opencode-ai/effect-drizzle-sqlite": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/util": "workspace:*",
@@ -388,7 +382,7 @@
"drizzle-orm": "catalog:",
"effect": "catalog:",
"fuzzysort": "3.1.0",
"gitlab-ai-provider": "6.11.1",
"gitlab-ai-provider": "6.12.1",
"google-auth-library": "10.5.0",
"gray-matter": "4.0.3",
"htmlparser2": "8.0.2",
@@ -405,6 +399,8 @@
"zod": "catalog:",
},
"devDependencies": {
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@opencode-ai/http-recorder": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
@@ -424,21 +420,22 @@
},
"packages/desktop": {
"name": "@opencode-ai/desktop",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@zip.js/zip.js": "2.7.62",
"drizzle-orm": "catalog:",
"effect": "catalog:",
"electron-context-menu": "4.1.2",
"electron-log": "^5",
"electron-store": "11.0.2",
"electron-updater": "6.8.9",
"electron-window-state": "^5.0.3",
"marked": "^15",
},
"devDependencies": {
"@actions/artifact": "4.0.0",
"@lydell/node-pty": "catalog:",
"@opencode-ai/app": "workspace:*",
"@opencode-ai/client": "workspace:*",
"@opencode-ai/ui": "workspace:*",
"@sentry/solid": "catalog:",
"@sentry/vite-plugin": "catalog:",
@@ -476,23 +473,9 @@
"@parcel/watcher-win32-x64": "2.5.1",
},
},
"packages/effect-drizzle-sqlite": {
"name": "@opencode-ai/effect-drizzle-sqlite",
"version": "1.18.8",
"dependencies": {
"drizzle-orm": "catalog:",
"effect": "catalog:",
},
"devDependencies": {
"@effect/sql-sqlite-bun": "catalog:",
"@tsconfig/bun": "catalog:",
"@types/bun": "catalog:",
"@typescript/native-preview": "catalog:",
},
},
"packages/enterprise": {
"name": "@opencode-ai/enterprise",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@hono/standard-validator": "catalog:",
"@opencode-ai/core": "workspace:*",
@@ -525,7 +508,7 @@
},
"packages/function": {
"name": "@opencode-ai/function",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "catalog:",
@@ -541,7 +524,7 @@
},
"packages/http-recorder": {
"name": "@opencode-ai/http-recorder",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@effect/platform-node-shared": "4.0.0-beta.101",
},
@@ -577,6 +560,7 @@
"dependencies": {
"@opencode-ai/plugin": "workspace:*",
"@opentui/core": "catalog:",
"entities": "7.0.1",
"string-width": "catalog:",
},
"devDependencies": {
@@ -587,7 +571,7 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@ai-sdk/provider": "3.0.8",
"@opencode-ai/ai": "workspace:*",
@@ -612,9 +596,9 @@
},
"peerDependencies": {
"@opencode-ai/theme": "workspace:*",
"@opentui/core": ">=0.4.5",
"@opentui/keymap": ">=0.4.5",
"@opentui/solid": ">=0.4.5",
"@opentui/core": "0.0.0-20260808-9ecf7c0a",
"@opentui/keymap": "0.0.0-20260808-9ecf7c0a",
"@opentui/solid": "0.0.0-20260808-9ecf7c0a",
"solid-js": ">=1.9.0",
},
"optionalPeers": [
@@ -703,7 +687,7 @@
},
"packages/session-ui": {
"name": "@opencode-ai/session-ui",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@kobalte/core": "catalog:",
"@opencode-ai/client": "workspace:*",
@@ -718,15 +702,11 @@
"@solid-primitives/media": "2.3.3",
"@solid-primitives/resize-observer": "2.1.3",
"@solidjs/meta": "catalog:",
"@solidjs/router": "catalog:",
"diff": "catalog:",
"dompurify": "3.3.1",
"fuzzysort": "catalog:",
"katex": "0.16.27",
"luxon": "catalog:",
"marked": "catalog:",
"marked-katex-extension": "5.1.6",
"marked-shiki": "catalog:",
"morphdom": "2.7.8",
"motion": "12.34.5",
"remeda": "catalog:",
@@ -739,7 +719,6 @@
"devDependencies": {
"@tsconfig/node22": "catalog:",
"@types/bun": "catalog:",
"@types/katex": "0.16.7",
"@types/luxon": "catalog:",
"@typescript/native-preview": "catalog:",
"typescript": "catalog:",
@@ -770,7 +749,7 @@
},
"packages/slack": {
"name": "@opencode-ai/slack",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@opencode-ai/sdk": "1.18.5",
"@slack/bolt": "^3.17.1",
@@ -783,7 +762,7 @@
},
"packages/stats/app": {
"name": "@opencode-ai/stats-app",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@ibm/plex": "6.4.1",
"@kobalte/core": "catalog:",
@@ -817,7 +796,7 @@
},
"packages/stats/core": {
"name": "@opencode-ai/stats-core",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@aws-sdk/client-athena": "3.933.0",
"@planetscale/database": "1.19.0",
@@ -836,7 +815,7 @@
},
"packages/stats/server": {
"name": "@opencode-ai/stats-server",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@aws-sdk/client-firehose": "3.933.0",
"@effect/platform-node": "catalog:",
@@ -907,7 +886,6 @@
"@opentui/keymap": "catalog:",
"@opentui/solid": "catalog:",
"@solid-primitives/event-bus": "1.1.2",
"clipboardy": "4.0.0",
"effect": "catalog:",
"fuzzysort": "catalog:",
"get-east-asian-width": "catalog:",
@@ -927,7 +905,7 @@
},
"packages/ui": {
"name": "@opencode-ai/ui",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@kobalte/core": "catalog:",
"@pierre/diffs": "catalog:",
@@ -943,7 +921,6 @@
"katex": "0.16.27",
"luxon": "catalog:",
"marked": "catalog:",
"marked-katex-extension": "5.1.6",
"marked-shiki": "catalog:",
"morphdom": "2.7.8",
"motion": "12.34.5",
@@ -953,6 +930,7 @@
"remend": "catalog:",
"shiki": "catalog:",
"solid-list": "catalog:",
"solid-sonner": "catalog:",
"strip-ansi": "7.1.2",
},
"devDependencies": {
@@ -1024,7 +1002,7 @@
},
"packages/web": {
"name": "@opencode-ai/web",
"version": "1.18.8",
"version": "1.18.15",
"dependencies": {
"@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1",
@@ -1079,21 +1057,24 @@
"tree-sitter-bash",
],
"patchedDependencies": {
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
"@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch",
"effect@4.0.0-beta.101": "patches/effect@4.0.0-beta.101.patch",
"@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch",
"@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch",
"@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch",
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
"@ai-sdk/mistral@3.0.51": "patches/@ai-sdk%2Fmistral@3.0.51.patch",
"@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch",
"@ff-labs/fff-bun@0.10.1": "patches/@ff-labs%2Ffff-bun@0.10.1.patch",
"@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch",
"@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch",
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
"@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch",
"@dnd-kit/dom@0.5.0": "patches/@dnd-kit%2Fdom@0.5.0.patch",
"@ai-sdk/openai-compatible@2.0.41": "patches/@ai-sdk%2Fopenai-compatible@2.0.41.patch",
},
"overrides": {
"@opentui/core": "catalog:",
"@opentui/keymap": "catalog:",
"@opentui/solid": "catalog:",
"@opentui/core": "0.0.0-20260808-9ecf7c0a",
"@opentui/keymap": "0.0.0-20260808-9ecf7c0a",
"@opentui/solid": "0.0.0-20260808-9ecf7c0a",
"@types/bun": "catalog:",
"@types/node": "catalog:",
"effect": "catalog:",
@@ -1111,9 +1092,9 @@
"@npmcli/arborist": "9.4.0",
"@octokit/rest": "22.0.0",
"@openauthjs/openauth": "0.0.0-20250322224806",
"@opentui/core": "0.4.5",
"@opentui/keymap": "0.4.5",
"@opentui/solid": "0.4.5",
"@opentui/core": "0.0.0-20260808-9ecf7c0a",
"@opentui/keymap": "0.0.0-20260808-9ecf7c0a",
"@opentui/solid": "0.0.0-20260808-9ecf7c0a",
"@pierre/diffs": "1.2.10",
"@playwright/test": "1.59.1",
"@sentry/solid": "10.36.0",
@@ -1146,7 +1127,7 @@
"hono": "4.10.7",
"hono-openapi": "1.1.2",
"luxon": "3.6.1",
"marked": "17.0.6",
"marked": "18.0.7",
"marked-shiki": "1.2.1",
"opentui-spinner": "0.0.7",
"remeda": "2.26.0",
@@ -1156,6 +1137,7 @@
"shiki": "4.2.0",
"solid-js": "1.9.10",
"solid-list": "0.3.0",
"solid-sonner": "0.3.1",
"sst": "4.13.1",
"string-width": "7.2.0",
"tailwindcss": "4.1.11",
@@ -2088,8 +2070,6 @@
"@opencode-ai/desktop": ["@opencode-ai/desktop@workspace:packages/desktop"],
"@opencode-ai/effect-drizzle-sqlite": ["@opencode-ai/effect-drizzle-sqlite@workspace:packages/effect-drizzle-sqlite"],
"@opencode-ai/enterprise": ["@opencode-ai/enterprise@workspace:packages/enterprise"],
"@opencode-ai/function": ["@opencode-ai/function@workspace:packages/function"],
@@ -2170,27 +2150,27 @@
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="],
"@opentui/core": ["@opentui/core@0.4.5", "", { "dependencies": { "bun-ffi-structs": "0.2.4", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.4.5", "@opentui/core-darwin-x64": "0.4.5", "@opentui/core-linux-arm64": "0.4.5", "@opentui/core-linux-arm64-musl": "0.4.5", "@opentui/core-linux-x64": "0.4.5", "@opentui/core-linux-x64-musl": "0.4.5", "@opentui/core-win32-arm64": "0.4.5", "@opentui/core-win32-x64": "0.4.5" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-JsgRTPkA6e+Vxmumxai6SElOSlRQkbzNKHlCfemlArRiLhfC1IZ9RXJo2QH4xSu+uBOWAM90uss73/pPlkdEig=="],
"@opentui/core": ["@opentui/core@0.0.0-20260808-9ecf7c0a", "", { "dependencies": { "bun-ffi-structs": "0.3.1", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.0.0-20260808-9ecf7c0a", "@opentui/core-darwin-x64": "0.0.0-20260808-9ecf7c0a", "@opentui/core-linux-arm64": "0.0.0-20260808-9ecf7c0a", "@opentui/core-linux-arm64-musl": "0.0.0-20260808-9ecf7c0a", "@opentui/core-linux-x64": "0.0.0-20260808-9ecf7c0a", "@opentui/core-linux-x64-musl": "0.0.0-20260808-9ecf7c0a", "@opentui/core-win32-arm64": "0.0.0-20260808-9ecf7c0a", "@opentui/core-win32-x64": "0.0.0-20260808-9ecf7c0a" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-y9MKL8LMup4ebW3uZ57RSsPyOv37sIZxuWiHq4XJK9wrzpzTMnVomzxpWOI0S/QtLH2QzZ7znnbF+IuvIQ1hLQ=="],
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.4.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8KUG0oRidnR+oW1RSZJ72/PhZLl+qRRMk5U/mieF4c0SJ5V3tYACpBZAKzQfHNd1f7QzD8FHZct1lPpQgtmkWg=="],
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.0.0-20260808-9ecf7c0a", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Bn6fUZrwbUojkJG4YHowg/h/u3SPANmEivrl8YVbxBPCYOhZzQWxAVf7Fwg6PD0BpWk5gt9inQrir2DzWh5UpA=="],
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.4.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-R2bocsg55gwjOqCp/MWFgFYzRmsduKegB6nzgFAPCvAD/L5Jf30xpWJWFlSg3x8vxe1L9WJ84dfqa4M7mZZ3wA=="],
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.0.0-20260808-9ecf7c0a", "", { "os": "darwin", "cpu": "x64" }, "sha512-lrVskzbjcT9yJCUgjOpvPpEq2ipmuDyHTMJ+OebsJFdATdryJLzRAr5BZiFGXEo4CJ2CS/+6vT+ki7dmhpM+0g=="],
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.4.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-R4MZ25a4CzOAGVjW9aj1hUfzQGVfCJwrwBDbNs2SXaIvzcZqkxCVtU4FoQ5LsaD0j/BdNQVg2CIfFkFsm1fDuQ=="],
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.0.0-20260808-9ecf7c0a", "", { "os": "linux", "cpu": "arm64" }, "sha512-czqIqdnBvyFRSJ0BEdNn7moRN0KQo5gvhSsOSfrzueHxsktgWcmk1cMeCvTkzC3JCBvCwlB1KnSdt4jlwNO1EQ=="],
"@opentui/core-linux-arm64-musl": ["@opentui/core-linux-arm64-musl@0.4.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ieqdyKI6EIYPalYAETB2wsdP83hr5Ifi+dFnBFUmdEEFHsoKwBmn2S7bsTOYlX7Bg03F4/YPIg+IvRpeC+cUJw=="],
"@opentui/core-linux-arm64-musl": ["@opentui/core-linux-arm64-musl@0.0.0-20260808-9ecf7c0a", "", { "os": "linux", "cpu": "arm64" }, "sha512-6nixv6wlgjelUVJVHkJsCpuARb1rE/oxhIIthyLd062u5veoBt83cRGH9KmcZiwowKvso58hXn2KC21qAfylhQ=="],
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.4.5", "", { "os": "linux", "cpu": "x64" }, "sha512-SNyuQoxMKI1vuJhgxSSW96adWM6LqFl2SoS3GM4tGeneGOanVVG2Y06PvlytXvF4cKik97t0rqkVMRetmOs93w=="],
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.0.0-20260808-9ecf7c0a", "", { "os": "linux", "cpu": "x64" }, "sha512-cxJMfrSsMsrZdU1Ke6awrxz0rdIJuI34l8Le3QlUbM5yLpp09ygJ7CElILMT50g3F+EnRf6BKvVmkbRrDzFQ6g=="],
"@opentui/core-linux-x64-musl": ["@opentui/core-linux-x64-musl@0.4.5", "", { "os": "linux", "cpu": "x64" }, "sha512-mKVKcIcPiSVVZZsdPSBoWwoa2/TCeQAaMDeHF7PFw2kt5bTXZPP7xxWfRQLCNIcA1eaGl59UuwUWHDR2Ve548Q=="],
"@opentui/core-linux-x64-musl": ["@opentui/core-linux-x64-musl@0.0.0-20260808-9ecf7c0a", "", { "os": "linux", "cpu": "x64" }, "sha512-7zVbZ0XgCDi3yImmd9Cj+e0WhSuQzWo1ziSQiFgPCR8cs/dfrpYLgBlX9PP0gFOcJKeRccJJv7rnBetl3CB7tg=="],
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.4.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-GHTTsqeR45q2Iek9Rb7ty+x/hAKn2jZ1ujlCgPR8LBKyF7h0E1dNFryoZ7ehMc3kJndP1sKn836IemKFqxuDdQ=="],
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.0.0-20260808-9ecf7c0a", "", { "os": "win32", "cpu": "arm64" }, "sha512-K3SNYJDvB7XD5nxi8jt4jWtgmqPG0Qbob0Px9afqMH3g/R5hIoi2P3GDbqn8JNv82c4dPIGJjXXuNhHa0tZQbw=="],
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.4.5", "", { "os": "win32", "cpu": "x64" }, "sha512-Y8T/yXCDGagRGiQrtmuB6AhRcPucKFs/Dre3v8kJwNYqDccI4FzUPKclZ7djfmRZNjl7JUqPhZZP/PwDpQocMg=="],
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.0.0-20260808-9ecf7c0a", "", { "os": "win32", "cpu": "x64" }, "sha512-3JCpPS8+Gz3PWlQHiFwqYuJ0AM0vKlfbe4+O+0m2EYej/QjN5KjL1nBfVLq5XDj4dVPEIktQKN6e//YzSzdaqA=="],
"@opentui/keymap": ["@opentui/keymap@0.4.5", "", { "dependencies": { "@opentui/core": "0.4.5" }, "peerDependencies": { "@opentui/react": "0.4.5", "@opentui/solid": "0.4.5", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-S1wzKHhF70zT6bH+VBFY+lSeTImLcIFW28JNQiME8MoPcy6KGPs7rKFSHrb/U7P8rsTJeRfW5A4d1Cy6PKodDg=="],
"@opentui/keymap": ["@opentui/keymap@0.0.0-20260808-9ecf7c0a", "", { "dependencies": { "@opentui/core": "0.0.0-20260808-9ecf7c0a" }, "peerDependencies": { "@opentui/react": "0.0.0-20260808-9ecf7c0a", "@opentui/solid": "0.0.0-20260808-9ecf7c0a", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-aGxw6P0RJSuUU3y3QtAnKa1B6tQShxR0mjmnN3Cadr4LoduSuWn/l1kE+27KwH0ap9WTAeGVsN7u2oawB9eWKw=="],
"@opentui/solid": ["@opentui/solid@0.4.5", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.4.5", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-B0RSkXnrtPVfEJOX+Hj+axjLJ3lzbG1BZw5I7Pvb9OPp48Vzg2cW2a3cSa86/q48ndLt647i/XwFPIw/jqnI5g=="],
"@opentui/solid": ["@opentui/solid@0.0.0-20260808-9ecf7c0a", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.0.0-20260808-9ecf7c0a", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-Q7ouv2KxZKO0/Sh0RbhNd7kEw6E7tlrU+yw36xxlnyXOqlK3TkQ+u1RMSZulYAn8mP20pnYLM9OxY4pOC/wK8Q=="],
"@orama/orama": ["@orama/orama@3.1.18", "", {}, "sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA=="],
@@ -3540,7 +3520,7 @@
"builder-util-runtime": ["builder-util-runtime@9.7.0", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw=="],
"bun-ffi-structs": ["bun-ffi-structs@0.2.4", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-AJzsqoVFs1KBbJbWHIYrVZLDC3NhTqqh25awRXqzoLzmBAKr5oqk6+CwuYHAekKx+VBCYVohBoKuRq40dV+TYg=="],
"bun-ffi-structs": ["bun-ffi-structs@0.3.1", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-3gM7PpVWLyrwxWjcilSiGuhWanhZivvo6l0u573NziPH6f/gwk6McbaYgn7oJWov6pKGRTDbrg94W5DcJsKTtQ=="],
"bun-pty": ["bun-pty@0.4.8", "", {}, "sha512-rO70Mrbr13+jxHHHu2YBkk2pNqrJE5cJn29WE++PUr+GFA0hq/VgtQPZANJ8dJo6d7XImvBk37Innt8GM7O28w=="],
@@ -3624,8 +3604,6 @@
"cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
"clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="],
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
@@ -3654,7 +3632,7 @@
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
@@ -4042,7 +4020,7 @@
"eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="],
"execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
"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=="],
"exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="],
@@ -4192,7 +4170,7 @@
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
"gitlab-ai-provider": ["gitlab-ai-provider@6.11.1", "", { "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-SJ6f5qa7P8md6lPrserryER3zerLkrezlnqqYQ2AbvDPpHLbwtbyk0FYJ5kNRcmbI80i/VMcsMBP0YIRdc3ucQ=="],
"gitlab-ai-provider": ["gitlab-ai-provider@6.12.1", "", { "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-Qn5iHqvjG8yktI5MWaUgdRR94l7O4WtYW0CAbhsCh1Tj0Fei/DeprOYPVyf4Nht1Ix6U2PXSYM32QOHI6Z2TDw=="],
"glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
@@ -4324,7 +4302,7 @@
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
"humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="],
@@ -4468,8 +4446,6 @@
"is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
"is64bit": ["is64bit@2.0.0", "", { "dependencies": { "system-architecture": "^0.1.0" } }, "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw=="],
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
"isbinaryfile": ["isbinaryfile@5.0.7", "", {}, "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ=="],
@@ -4666,9 +4642,7 @@
"markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
"marked": ["marked@17.0.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA=="],
"marked-katex-extension": ["marked-katex-extension@5.1.6", "", { "peerDependencies": { "katex": ">=0.16 <0.17", "marked": ">=4 <18" } }, "sha512-vYpLXwmlIDKILIhJtiRTgdyZRn5sEYdFBuTmbpjD7lbCIzg0/DWyK3HXIntN3Tp8zV6hvOUgpZNLWRCgWVc24A=="],
"marked": ["marked@18.0.7", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-iDVQ5ldaiKXn6b2JroX5kgRfmwgqolW7NpaEzTl1k/2Zh1njIEN9yniyLV/mOvWwtsE8OGgkjsCYvijuPk1dtA=="],
"marked-shiki": ["marked-shiki@1.2.1", "", { "peerDependencies": { "marked": ">=7.0.0", "shiki": ">=1.0.0" } }, "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ=="],
@@ -4810,7 +4784,7 @@
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
@@ -4936,7 +4910,7 @@
"npm-registry-fetch": ["npm-registry-fetch@19.1.1", "", { "dependencies": { "@npmcli/redact": "^4.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^13.0.0", "proc-log": "^6.0.0" } }, "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw=="],
"npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
@@ -4962,7 +4936,7 @@
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
"onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="],
@@ -5468,6 +5442,8 @@
"solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="],
"solid-sonner": ["solid-sonner@0.3.1", "", { "peerDependencies": { "solid-js": "^1.6.0" } }, "sha512-F/+zi9yKJTHh5hX1UGJfkDvyC+F34Vi3jgy44NJwOKCgic1QtAon0b1iT9OsDO77RTgR+PCil+3Y5B8T2Owy1Q=="],
"solid-stripe": ["solid-stripe@0.8.1", "", { "peerDependencies": { "@stripe/stripe-js": ">=1.44.1 <8.0.0", "solid-js": "^1.6.0" } }, "sha512-l2SkWoe51rsvk9u1ILBRWyCHODZebChSGMR6zHYJTivTRC0XWrRnNNKs5x1PYXsaIU71KYI6ov5CZB5cOtGLWw=="],
"solid-transition-size": ["solid-transition-size@0.1.4", "", { "dependencies": { "@corvu/utils": "~0.3.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-ocHVnbfy23CgfaH4cEUR/AFg0Y3CEL8Oh3n9Qv8OHFJgPh+zkmERKZQfi/xH5XvxDCizg8VjPrVUhiHB1Gza8g=="],
@@ -5562,7 +5538,7 @@
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
"strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="],
@@ -5594,8 +5570,6 @@
"svgo": ["svgo@4.0.2", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng=="],
"system-architecture": ["system-architecture@0.1.0", "", {}, "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA=="],
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
"tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
@@ -6382,8 +6356,6 @@
"@opencode-ai/desktop/@actions/artifact": ["@actions/artifact@4.0.0", "", { "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^6.0.1", "@actions/http-client": "^2.1.0", "@azure/core-http": "^3.0.5", "@azure/storage-blob": "^12.15.0", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-HCc2jMJRAfviGFAh0FsOR/jNfWhirxl7W6z8zDtttt0GltwxBLdEIjLiweOPFl9WbyJRW1VWnPUSAixJqcWUMQ=="],
"@opencode-ai/desktop/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="],
"@opencode-ai/desktop/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="],
"@opencode-ai/session-ui/@opencode-ai/sdk": ["@opencode-ai/sdk@../app/vendor/opencode-ai-sdk-1.18.8-dev.tgz", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-C2nfk4x0sPINwE5V6DPkFSuH3PkUmKPWHPzxpXC1j+3Ui5hslLCWJbkk8WcOG1Lyt3C0+yp4ea64v/kmtYCO4w=="],
@@ -6536,8 +6508,6 @@
"@vercel/cli-config/zod": ["zod@4.1.11", "", {}, "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg=="],
"@vercel/cli-exec/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=="],
"@vercel/functions/@vercel/oidc": ["@vercel/oidc@3.8.1", "", { "dependencies": { "@vercel/cli-config": "0.2.1", "@vercel/cli-exec": "1.0.0", "jose": "^5.9.6" } }, "sha512-ufdalm2MWOYksyj8KVpWjoOFPJO6zoYpuyvIggIQ2bB0CFCjTCiTkGXHqAKwG77GVRjOaN3/8S5ITlZpXWmqOw=="],
"@vercel/nft/acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
@@ -6624,8 +6594,6 @@
"blume/katex": ["katex@0.17.0", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw=="],
"blume/marked": ["marked@18.0.7", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-iDVQ5ldaiKXn6b2JroX5kgRfmwgqolW7NpaEzTl1k/2Zh1njIEN9yniyLV/mOvWwtsE8OGgkjsCYvijuPk1dtA=="],
"blume/node-html-parser": ["node-html-parser@9.0.0", "", { "dependencies": { "css-select": "^5.1.0", "entities": "^8.0.0" } }, "sha512-MhdaHPyxnyYu/sf0TpiRvDnTrkum0UKHC7FdbDGIUQNlx3I7xzwXoyV0eMUMv/XU+lkJT1glOUzpDPq7b2p1Ew=="],
"blume/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="],
@@ -6724,9 +6692,11 @@
"estree-util-to-js/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
"execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
"execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
"execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
"execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
"execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
@@ -6760,6 +6730,8 @@
"jszip/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
"matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
@@ -6800,8 +6772,6 @@
"node-gyp/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
"openid-client/jose": ["jose@4.15.9", "", {}, "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA=="],
"openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
@@ -6890,12 +6860,8 @@
"terser/acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
"topojson-client/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"tree-sitter-bash/node-addon-api": ["node-addon-api@8.9.0", "", {}, "sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q=="],
"tw-to-css/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
@@ -7572,20 +7538,6 @@
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
"@vercel/cli-exec/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
"@vercel/cli-exec/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
"@vercel/cli-exec/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
"@vercel/cli-exec/execa/npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
"@vercel/cli-exec/execa/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"@vercel/cli-exec/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"@vercel/cli-exec/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
"@vercel/functions/@vercel/oidc/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
"@vercel/routing-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
@@ -7718,6 +7670,8 @@
"blume/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"blume/katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"blume/node-html-parser/entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="],
"blume/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
@@ -7790,6 +7744,8 @@
"lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
"mermaid/katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"motion/framer-motion/motion-dom": ["motion-dom@12.42.2", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA=="],
"motion/framer-motion/motion-utils": ["motion-utils@12.39.0", "", {}, "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ=="],
@@ -8642,8 +8598,6 @@
"@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="],
"@vercel/cli-exec/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
+6 -2
View File
@@ -288,8 +288,12 @@ new sst.cloudflare.x.SolidStart("Console", {
server: {
placement: { region: "aws:us-east-2" },
transform: {
worker: {
tailConsumers: [{ service: logProcessor.nodes.worker.scriptName }],
worker: (args) => {
args.compatibilityFlags = $resolve(args.compatibilityFlags).apply((flags) => [
...(flags ?? []),
"global_fetch_strictly_public",
])
args.tailConsumers = [{ service: logProcessor.nodes.worker.scriptName }]
},
},
},
+45 -53
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
APP=opencode
APP=opencode2
MUTED='\033[0;2m'
RED='\033[0;31m'
@@ -15,14 +15,14 @@ Usage: install.sh [options]
Options:
-h, --help Display this help message
-v, --version <version> Install a specific version (e.g., 1.0.180)
-v, --version <version> Install a specific version (e.g., 0.0.0-next-17236)
-b, --binary <path> Install from a local binary instead of downloading
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
Examples:
curl -fsSL https://opencode.ai/install | bash
curl -fsSL https://opencode.ai/install | bash -s -- --version 1.0.180
./install --binary /path/to/opencode
curl -fsSL https://raw.githubusercontent.com/anomalyco/opencode/v2/install | bash
curl -fsSL https://raw.githubusercontent.com/anomalyco/opencode/v2/install | bash -s -- --version 0.0.0-next-17236
./install --binary /path/to/opencode2
EOF
}
@@ -109,11 +109,6 @@ else
;;
esac
archive_ext=".zip"
if [ "$os" = "linux" ]; then
archive_ext=".tar.gz"
fi
is_musl=false
if [ "$os" = "linux" ]; then
if [ -f /etc/alpine-release ]; then
@@ -165,42 +160,42 @@ else
target="$target-musl"
fi
filename="$APP-$target$archive_ext"
if [ "$os" = "linux" ]; then
if ! command -v tar >/dev/null 2>&1; then
echo -e "${RED}Error: 'tar' is required but not installed.${NC}"
exit 1
fi
else
if ! command -v unzip >/dev/null 2>&1; then
echo -e "${RED}Error: 'unzip' is required but not installed.${NC}"
exit 1
fi
if ! command -v tar >/dev/null 2>&1; then
echo -e "${RED}Error: 'tar' is required but not installed.${NC}"
exit 1
fi
if [ -z "$requested_version" ]; then
url="https://github.com/anomalyco/opencode/releases/latest/download/$filename"
specific_version=$(curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
metadata=$(curl -fsSL https://registry.npmjs.org/@opencode-ai%2fcli/next || true)
specific_version=$(echo "$metadata" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
if [[ $? -ne 0 || -z "$specific_version" ]]; then
if [ -z "$specific_version" ]; then
echo -e "${RED}Failed to fetch version information${NC}"
exit 1
fi
else
# Strip leading 'v' if present
requested_version="${requested_version#v}"
url="https://github.com/anomalyco/opencode/releases/download/v${requested_version}/$filename"
specific_version=$requested_version
fi
# Verify the release exists before downloading
http_status=$(curl -sI -o /dev/null -w "%{http_code}" "https://github.com/anomalyco/opencode/releases/tag/v${requested_version}")
if [ "$http_status" = "404" ]; then
echo -e "${RED}Error: Release v${requested_version} not found${NC}"
echo -e "${MUTED}Available releases: https://github.com/anomalyco/opencode/releases${NC}"
exit 1
fi
package_name="@opencode-ai/cli-$target"
http_status=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/@opencode-ai%2fcli-$target/$specific_version" || true)
if [ "$http_status" = "404" ]; then
echo -e "${RED}Error: Version ${specific_version} is not available for $target${NC}"
echo -e "${MUTED}Available versions: https://www.npmjs.com/package/$package_name?activeTab=versions${NC}"
exit 1
fi
if [ "$http_status" != "200" ]; then
echo -e "${RED}Failed to fetch package information${NC}"
exit 1
fi
filename="cli-$target-$specific_version.tgz"
url="https://registry.npmjs.org/$package_name/-/$filename"
binary_name="$APP"
if [ "$os" = "windows" ]; then
binary_name="$APP.exe"
fi
fi
@@ -219,11 +214,13 @@ print_message() {
}
check_version() {
if command -v opencode >/dev/null 2>&1; then
opencode_path=$(which opencode)
if command -v "$APP" >/dev/null 2>&1; then
opencode_path=$(which "$APP")
## Check the installed version
installed_version=$(opencode --version 2>/dev/null || echo "")
installed_version=$("$APP" --version 2>/dev/null || echo "")
installed_version="${installed_version##* }"
installed_version="${installed_version#v}"
if [[ "$installed_version" != "$specific_version" ]]; then
print_message info "${MUTED}Installed version: ${NC}$installed_version."
@@ -287,7 +284,7 @@ download_with_progress() {
trap "trap - RETURN; rm -f \"$tracefile\"; printf '\033[?25h' >&4; exec 4>&-" RETURN
(
curl --trace-ascii "$tracefile" -s -L -o "$output" "$url"
curl --trace-ascii "$tracefile" -fsL -o "$output" "$url"
) &
local curl_pid=$!
@@ -325,30 +322,25 @@ download_with_progress() {
}
download_and_install() {
print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}version: ${NC}$specific_version"
print_message info "\n${MUTED}Installing ${NC}$APP ${MUTED}version: ${NC}$specific_version"
local tmp_dir="${TMPDIR:-/tmp}/opencode_install_$$"
mkdir -p "$tmp_dir"
if [[ "$os" == "windows" ]] || ! [ -t 2 ] || ! download_with_progress "$url" "$tmp_dir/$filename"; then
# Fallback to standard curl on Windows, non-TTY environments, or if custom progress fails
curl -# -L -o "$tmp_dir/$filename" "$url"
curl -f -# -L -o "$tmp_dir/$filename" "$url"
fi
if [ "$os" = "linux" ]; then
tar -xzf "$tmp_dir/$filename" -C "$tmp_dir"
else
unzip -q "$tmp_dir/$filename" -d "$tmp_dir"
fi
mv "$tmp_dir/opencode" "$INSTALL_DIR"
chmod 755 "${INSTALL_DIR}/opencode"
tar -xzf "$tmp_dir/$filename" -C "$tmp_dir"
mv "$tmp_dir/package/bin/$binary_name" "$INSTALL_DIR"
chmod 755 "${INSTALL_DIR}/$binary_name"
rm -rf "$tmp_dir"
}
install_from_binary() {
print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}from: ${NC}$binary_path"
cp "$binary_path" "${INSTALL_DIR}/opencode"
chmod 755 "${INSTALL_DIR}/opencode"
print_message info "\n${MUTED}Installing ${NC}$APP ${MUTED}from: ${NC}$binary_path"
cp "$binary_path" "${INSTALL_DIR}/$APP"
chmod 755 "${INSTALL_DIR}/$APP"
}
if [ -n "$binary_path" ]; then
@@ -453,8 +445,8 @@ echo -e ""
echo -e "${MUTED}OpenCode includes free models, to start:${NC}"
echo -e ""
echo -e "cd <project> ${MUTED}# Open directory${NC}"
echo -e "opencode ${MUTED}# Run command${NC}"
echo -e "opencode2 ${MUTED}# Run command${NC}"
echo -e ""
echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/docs"
echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/v2/docs"
echo -e ""
echo -e ""
+4 -4
View File
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-RFek0QoEEjsgbqmTE/SxQAmPtYyzs0IPR2ugFn5Okrs=",
"aarch64-linux": "sha256-BmAxapY1YrAFn7mVq3/6A9+6Au5UIvSqBboHMkyJH3I=",
"aarch64-darwin": "sha256-Sx3bGWQqLlgoa/RudJxanjSzhFRNklckT2ffnO2I5F4=",
"x86_64-darwin": "sha256-CMOhiisHNowg06qadvgg4K+60zrynglwiT0qKYQ4NiA="
"x86_64-linux": "sha256-uduwrM143NDSc+tXsi4lVVfoMll2a3BDHRUjuO7GB68=",
"aarch64-linux": "sha256-6DUda78XdXY6DP86lIUkweSjys3iG4Y4mo1PiaNuXbg=",
"aarch64-darwin": "sha256-AkJwfLULLZVwwz+XU1QcFUZoIS7oVPCn+n/MXEaxrqE=",
"x86_64-darwin": "sha256-hAxKGdiITTxQ2uujQt6prNjo3NxGAMMeo+9HlMWK6GU="
}
}
+12 -8
View File
@@ -46,9 +46,9 @@
"@octokit/rest": "22.0.0",
"@hono/standard-validator": "0.2.0",
"@hono/zod-validator": "0.4.2",
"@opentui/core": "0.4.5",
"@opentui/keymap": "0.4.5",
"@opentui/solid": "0.4.5",
"@opentui/core": "0.0.0-20260808-9ecf7c0a",
"@opentui/keymap": "0.0.0-20260808-9ecf7c0a",
"@opentui/solid": "0.0.0-20260808-9ecf7c0a",
"@tanstack/solid-virtual": "3.13.32",
"@shikijs/stream": "4.2.0",
"@standard-schema/spec": "1.1.0",
@@ -78,7 +78,7 @@
"fuzzysort": "3.1.0",
"get-east-asian-width": "1.6.0",
"luxon": "3.6.1",
"marked": "17.0.6",
"marked": "18.0.7",
"marked-shiki": "1.2.1",
"remend": "1.3.0",
"@playwright/test": "1.59.1",
@@ -100,6 +100,7 @@
"@sentry/solid": "10.36.0",
"@sentry/vite-plugin": "4.6.0",
"solid-js": "1.9.10",
"solid-sonner": "0.3.1",
"vite-plugin-solid": "2.11.10",
"@lydell/node-pty": "1.2.0-beta.12"
}
@@ -149,14 +150,16 @@
"electron"
],
"overrides": {
"@opentui/core": "catalog:",
"@opentui/keymap": "catalog:",
"@opentui/solid": "catalog:",
"@opentui/core": "0.0.0-20260808-9ecf7c0a",
"@opentui/keymap": "0.0.0-20260808-9ecf7c0a",
"@opentui/solid": "0.0.0-20260808-9ecf7c0a",
"@types/bun": "catalog:",
"@types/node": "catalog:",
"effect": "catalog:"
},
"patchedDependencies": {
"@ai-sdk/openai-compatible@2.0.41": "patches/@ai-sdk%2Fopenai-compatible@2.0.41.patch",
"@dnd-kit/dom@0.5.0": "patches/@dnd-kit%2Fdom@0.5.0.patch",
"@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch",
"@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch",
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
@@ -168,6 +171,7 @@
"@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch",
"@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch",
"effect@4.0.0-beta.101": "patches/effect@4.0.0-beta.101.patch",
"@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch"
"@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch",
"@ff-labs/fff-bun@0.10.1": "patches/@ff-labs%2Ffff-bun@0.10.1.patch"
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ import * as fs from "node:fs/promises"
import * as path from "node:path"
const RECORDINGS_DIR = path.resolve(import.meta.dir, "..", "test", "fixtures", "recordings")
const MODELS_DEV_URL = "https://models.dev/api.json"
const MODELS_DEV_URL = "https://models.opencode.ai/api.json"
type JsonRecord = Record<string, unknown>
+2 -2
View File
@@ -10,8 +10,8 @@
//
// Manual `cache: CacheHint` placements on individual parts are preserved and
// count against the four-breakpoint budget; auto only fills remaining slots.
import { CacheHint, type CachePolicy, type CachePolicyObject } from "./schema/options"
import { LLMRequest, Message, ToolDefinition, type ContentPart } from "./schema/messages"
import { CacheHint, type CachePolicy, type CachePolicyObject } from "./schema/options.js"
import { LLMRequest, Message, ToolDefinition, type ContentPart } from "./schema/messages.js"
const AUTO: CachePolicyObject = {
tools: true,
+3 -3
View File
@@ -1,7 +1,7 @@
import { Context, Effect, Layer } from "effect"
import { RequestExecutor } from "./route/executor"
import type { ImageOptions, ImageRequest, ImageRequestFor, ImageResponse } from "./image"
import type { AIError } from "./schema"
import { RequestExecutor } from "./route/executor.js"
import type { ImageOptions, ImageRequest, ImageRequestFor, ImageResponse } from "./image.js"
import type { AIError } from "./schema/index.js"
export type Execute = RequestExecutor.Interface["execute"]
+10 -2
View File
@@ -1,6 +1,14 @@
import { Effect, Schema } from "effect"
import { HttpOptions, InvalidRequestReason, AIError, ModelID, ProviderID, ProviderMetadata, Usage } from "./schema"
import { ImageClient, Service, type Execute as ImageExecute } from "./image-client"
import {
HttpOptions,
InvalidRequestReason,
AIError,
ModelID,
ProviderID,
ProviderMetadata,
Usage,
} from "./schema/index.js"
import { ImageClient, Service, type Execute as ImageExecute } from "./image-client.js"
export interface ImageRoute<Options extends ImageOptions = ImageOptions> {
readonly id: string
+21 -18
View File
@@ -1,22 +1,22 @@
export { LLMClient } from "./route/client"
export { ImageClient } from "./image-client"
export { Auth } from "./route/auth"
export { Provider } from "./provider"
export { ProviderPackage } from "./provider-package"
export { isContextOverflow, isContextOverflowFailure } from "./provider-error"
export { LLMClient } from "./route/client.js"
export { ImageClient } from "./image-client.js"
export { Auth } from "./route/auth.js"
export { Provider } from "./provider.js"
export { ProviderPackage } from "./provider-package.js"
export { isContextOverflow, isContextOverflowFailure } from "./provider-error.js"
export type {
RouteLanguageModelInput,
RouteRoutedLanguageModelInput,
Interface as LLMClientShape,
Service as LLMClientService,
} from "./route/client"
export * from "./schema"
export { GeneratedImage, ImageInput, ImageInputSchema, ImageModel, ImageRequest, ImageResponse } from "./image"
export type { ImageModelOptions, ImageOptions, ImageRequestFor, ImageRequestInput, ImageRoute } from "./image"
export { Image } from "./image"
export { Tool, ToolFailure, toDefinitions } from "./tool"
export { ToolRuntime } from "./tool-runtime"
export type { DispatchResult as ToolDispatchResult, ToolSettlement } from "./tool-runtime"
} from "./route/client.js"
export * from "./schema/index.js"
export { GeneratedImage, ImageInput, ImageInputSchema, ImageModel, ImageRequest, ImageResponse } from "./image.js"
export type { ImageModelOptions, ImageOptions, ImageRequestFor, ImageRequestInput, ImageRoute } from "./image.js"
export { Image } from "./image.js"
export { Tool, ToolFailure, toDefinitions } from "./tool.js"
export { ToolRuntime } from "./tool-runtime.js"
export type { DispatchResult as ToolDispatchResult, ToolSettlement } from "./tool-runtime.js"
export type {
AnyExecutableTool,
AnyTool,
@@ -29,11 +29,14 @@ export type {
Tools,
ToolSchema,
ToolToModelOutput,
} from "./tool"
export * as LLM from "./llm"
} from "./tool.js"
export * as LLM from "./llm.js"
export type {
Definition as ProviderDefinition,
LanguageModelFactory as ProviderLanguageModelFactory,
LanguageModelOptions as ProviderLanguageModelOptions,
} from "./provider"
export type { Definition as ProviderPackageDefinition, Settings as ProviderPackageSettings } from "./provider-package"
} from "./provider.js"
export type {
Definition as ProviderPackageDefinition,
Settings as ProviderPackageSettings,
} from "./provider-package.js"
+3 -3
View File
@@ -1,5 +1,5 @@
import { Effect, JsonSchema, Schema } from "effect"
import { LLMClient, Service } from "./route/client"
import { LLMClient, Service } from "./route/client.js"
import {
GenerationOptions,
HttpOptions,
@@ -15,8 +15,8 @@ import {
ToolDefinition,
type ContentPart,
type LanguageModelProviderOptions,
} from "./schema"
import { make as makeTool, toDefinitions, type ToolSchema } from "./tool"
} from "./schema/index.js"
import { make as makeTool, toDefinitions, type ToolSchema } from "./tool.js"
/** Input accepted by `LLM.request`, normalized into the canonical `LLMRequest` class. */
export type RequestInput<SelectedLanguageModel extends LanguageModel = LanguageModel> = Omit<
+1 -1
View File
@@ -1 +1 @@
export * from "./protocols/index"
export * from "./protocols/index.js"
+17 -14
View File
@@ -1,10 +1,10 @@
import { Effect, Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import { Route } from "../route/client"
import { Auth } from "../route/auth"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
import { Route } from "../route/client.js"
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 {
AIError,
LLMEvent,
@@ -21,13 +21,13 @@ import {
type ToolCallPart,
type ToolDefinition,
type ToolResultPart,
} from "../schema"
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared"
import { classifyProviderFailure } from "../provider-error"
import * as Cache from "./utils/cache"
import { Lifecycle } from "./utils/lifecycle"
import { ToolSchemaProjection } from "./utils/tool-schema"
import { ToolStream } from "./utils/tool-stream"
} from "../schema/index.js"
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js"
import { classifyProviderFailure } from "../provider-error.js"
import * as Cache from "./utils/cache.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
import { ToolStream } from "./utils/tool-stream.js"
const ADAPTER = "anthropic-messages"
const MEDIA_MIMES = new Set<string>([...ProviderShared.IMAGE_MIMES, ...ProviderShared.PDF_MIMES])
@@ -573,7 +573,10 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (
cache_control: cacheControl(breakpoints, part.cache),
})
}
messages.push({ role: "user", content })
const previous = messages.at(-1)
if (previous?.role === "user" && previous.content.every((block) => block.type === "tool_result"))
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] }
else messages.push({ role: "user", content })
}
return messages
@@ -1029,4 +1032,4 @@ export const route = Route.make({
headers: () => ({ "anthropic-version": "2023-06-01" }),
})
export * as AnthropicMessages from "./anthropic-messages"
export * as AnthropicMessages from "./anthropic-messages.js"
+23 -17
View File
@@ -1,7 +1,7 @@
import { Effect, Schema } from "effect"
import { Route } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Protocol } from "../route/protocol"
import { Route } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { Protocol } from "../route/protocol.js"
import {
AIError,
LLMEvent,
@@ -17,20 +17,20 @@ import {
type ToolCallPart,
type ToolDefinition,
type ToolResultPart,
} from "../schema"
import { BedrockEventStream } from "./bedrock-event-stream"
import { classifyProviderFailure } from "../provider-error"
import { JsonObject, optionalArray, ProviderShared } from "./shared"
import { BedrockAuth } from "./utils/bedrock-auth"
import { BedrockCache } from "./utils/bedrock-cache"
import { BedrockMedia } from "./utils/bedrock-media"
import { Lifecycle } from "./utils/lifecycle"
import { ToolSchemaProjection } from "./utils/tool-schema"
import { ToolStream } from "./utils/tool-stream"
} from "../schema/index.js"
import { BedrockEventStream } from "./bedrock-event-stream.js"
import { classifyProviderFailure } from "../provider-error.js"
import { JsonObject, optionalArray, ProviderShared } from "./shared.js"
import { BedrockAuth } from "./utils/bedrock-auth.js"
import { BedrockCache } from "./utils/bedrock-cache.js"
import { BedrockMedia } from "./utils/bedrock-media.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
import { ToolStream } from "./utils/tool-stream.js"
const ADAPTER = "bedrock-converse"
export type { Credentials as BedrockCredentials } from "./utils/bedrock-auth"
export type { Credentials as BedrockCredentials } from "./utils/bedrock-auth.js"
// =============================================================================
// Request Body Schema
@@ -348,7 +348,10 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
continue
}
}
messages.push({ role: "user", content })
const previous = messages.at(-1)
if (previous?.role === "user")
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] }
else messages.push({ role: "user", content })
continue
}
@@ -392,7 +395,10 @@ const lowerMessages = Effect.fn("BedrockConverse.lowerMessages")(function* (
const cachePoint = BedrockCache.block(breakpoints, part.cache)
if (cachePoint) content.push(cachePoint)
}
messages.push({ role: "user", content })
const previous = messages.at(-1)
if (previous?.role === "user")
messages[messages.length - 1] = { role: "user", content: [...previous.content, ...content] }
else messages.push({ role: "user", content })
}
return messages
@@ -731,4 +737,4 @@ export const route = Route.make({
export const sigV4Auth = BedrockAuth.sigV4
export * as BedrockConverse from "./bedrock-converse"
export * as BedrockConverse from "./bedrock-converse.js"
@@ -1,8 +1,8 @@
import { EventStreamCodec } from "@smithy/eventstream-codec"
import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
import { Effect, Stream } from "effect"
import { Framing } from "../route/framing"
import { ProviderShared } from "./shared"
import { Framing } from "../route/framing.js"
import { ProviderShared } from "./shared.js"
// Bedrock streams responses using the AWS event stream binary protocol — each
// frame is `[length:4][headers-length:4][prelude-crc:4][headers][payload][crc:4]`.
@@ -98,4 +98,4 @@ export const framing = (route: string): Framing.Definition<object> => ({
frame: (bytes) => bytes.pipe(Stream.mapAccumEffect(() => initialFrameBuffer, consumeFrames(route))),
})
export * as BedrockEventStream from "./bedrock-event-stream"
export * as BedrockEventStream from "./bedrock-event-stream.js"
+11 -11
View File
@@ -1,10 +1,10 @@
import { Effect, Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import { Route } from "../route/client"
import { Auth } from "../route/auth"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
import { Route } from "../route/client.js"
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 {
LLMEvent,
Usage,
@@ -17,11 +17,11 @@ import {
type TextPart,
type ToolCallPart,
type ToolDefinition,
} from "../schema"
import { JsonObject, optionalArray, ProviderShared } from "./shared"
import { GeminiToolSchema } from "./utils/gemini-tool-schema"
import { Lifecycle } from "./utils/lifecycle"
import { ToolSchemaProjection } from "./utils/tool-schema"
} from "../schema/index.js"
import { JsonObject, optionalArray, ProviderShared } from "./shared.js"
import { GeminiToolSchema } from "./utils/gemini-tool-schema.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
const ADAPTER = "gemini"
const MEDIA_MIMES = new Set<string>(ProviderShared.MEDIA_MIMES)
@@ -643,4 +643,4 @@ export const route = Route.make({
framing: Framing.sse,
})
export * as Gemini from "./gemini"
export * as Gemini from "./gemini.js"
+5 -5
View File
@@ -7,8 +7,8 @@ import {
type ImageInput,
type ImageRequestFor,
type ImageRoute,
} from "../image"
import { Auth, type Definition as AuthDefinition } from "../route/auth"
} from "../image.js"
import { Auth, type Definition as AuthDefinition } from "../route/auth.js"
import {
InvalidProviderOutputReason,
AIError,
@@ -17,9 +17,9 @@ import {
mergeJsonRecords,
type HttpOptions,
type ProviderMetadata,
} from "../schema"
import { ProviderShared } from "./shared"
import { ImageInputs } from "./utils/image-input"
} from "../schema/index.js"
import { ProviderShared } from "./shared.js"
import { ImageInputs } from "./utils/image-input.js"
const ADAPTER = "google-images"
export const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
+9 -9
View File
@@ -1,9 +1,9 @@
export * as AnthropicMessages from "./anthropic-messages"
export * as BedrockConverse from "./bedrock-converse"
export * as Gemini from "./gemini"
export * as OpenAIChat from "./openai-chat"
export * as OpenAIImages from "./openai-images"
export * as OpenAICompatibleChat from "./openai-compatible-chat"
export * as OpenAICompatibleResponses from "./openai-compatible-responses"
export * as OpenAIResponses from "./openai-responses"
export * as OpenResponses from "./open-responses"
export * as AnthropicMessages from "./anthropic-messages.js"
export * as BedrockConverse from "./bedrock-converse.js"
export * as Gemini from "./gemini.js"
export * as OpenAIChat from "./openai-chat.js"
export * as OpenAIImages from "./openai-images.js"
export * as OpenAICompatibleChat from "./openai-compatible-chat.js"
export * as OpenAICompatibleResponses from "./openai-compatible-responses.js"
export * as OpenAIResponses from "./openai-responses.js"
export * as OpenResponses from "./open-responses.js"
+10 -10
View File
@@ -1,7 +1,7 @@
import { Effect, Schema } from "effect"
import type { Content } from "@opencode-ai/schema/tool"
import { HttpTransport } from "../route/transport"
import { Protocol } from "../route/protocol"
import { HttpTransport } from "../route/transport/index.js"
import { Protocol } from "../route/protocol.js"
import {
AIError,
LLMEvent,
@@ -16,13 +16,13 @@ import {
type ToolCallPart,
type ToolDefinition,
type ToolResultPart,
} from "../schema"
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared"
import { classifyProviderFailure } from "../provider-error"
import { OpenResponsesOptions } from "./utils/open-responses-options"
import { Lifecycle } from "./utils/lifecycle"
import { ToolSchemaProjection } from "./utils/tool-schema"
import { ToolStream } from "./utils/tool-stream"
} from "../schema/index.js"
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js"
import { classifyProviderFailure } from "../provider-error.js"
import { OpenResponsesOptions } from "./utils/open-responses-options.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
import { ToolStream } from "./utils/tool-stream.js"
const ADAPTER = "open-responses"
const NAME = "Open Responses"
@@ -1061,4 +1061,4 @@ export const protocol = Protocol.make({
export const httpTransport = HttpTransport.sseJson.with<OpenResponsesBody>()
export * as OpenResponses from "./open-responses"
export * as OpenResponses from "./open-responses.js"
+13 -13
View File
@@ -1,10 +1,10 @@
import { Effect, Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import { Route } from "../route/client"
import { Auth } from "../route/auth"
import { Endpoint } from "../route/endpoint"
import { HttpTransport } from "../route/transport"
import { Protocol } from "../route/protocol"
import { Route } from "../route/client.js"
import { Auth } from "../route/auth.js"
import { Endpoint } from "../route/endpoint.js"
import { HttpTransport } from "../route/transport/index.js"
import { Protocol } from "../route/protocol.js"
import {
AIError,
LLMEvent,
@@ -19,13 +19,13 @@ import {
type TextPart,
type ToolCallPart,
type ToolDefinition,
} from "../schema"
import { classifyProviderFailure } from "../provider-error"
import { isRecord, JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared"
import { OpenAIOptions } from "./utils/openai-options"
import { Lifecycle } from "./utils/lifecycle"
import { ToolSchemaProjection } from "./utils/tool-schema"
import { ToolStream } from "./utils/tool-stream"
} from "../schema/index.js"
import { classifyProviderFailure } from "../provider-error.js"
import { isRecord, JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js"
import { OpenAIOptions } from "./utils/openai-options.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
import { ToolStream } from "./utils/tool-stream.js"
const ADAPTER = "openai-chat"
const IMAGE_MIMES = new Set<string>(ProviderShared.IMAGE_MIMES)
@@ -884,4 +884,4 @@ export const route = Route.make({
transport: httpTransport,
})
export * as OpenAIChat from "./openai-chat"
export * as OpenAIChat from "./openai-chat.js"
@@ -1,7 +1,7 @@
import { Route, type RouteRoutedLanguageModelInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import * as OpenAIChat from "./openai-chat"
import { Route, type RouteRoutedLanguageModelInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { Framing } from "../route/framing.js"
import * as OpenAIChat from "./openai-chat.js"
const ADAPTER = "openai-compatible-chat"
@@ -22,4 +22,4 @@ export const route = Route.make({
framing: Framing.sse,
})
export * as OpenAICompatibleChat from "./openai-compatible-chat"
export * as OpenAICompatibleChat from "./openai-compatible-chat.js"
@@ -1,6 +1,6 @@
import { Route, type RouteRoutedLanguageModelInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { OpenResponses } from "./open-responses"
import { Route, type RouteRoutedLanguageModelInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { OpenResponses } from "./open-responses.js"
const ADAPTER = "openai-compatible-responses"
@@ -19,4 +19,4 @@ export const route = Route.make({
transport: OpenResponses.httpTransport,
})
export * as OpenAICompatibleResponses from "./openai-compatible-responses"
export * as OpenAICompatibleResponses from "./openai-compatible-responses.js"
+6 -6
View File
@@ -7,8 +7,8 @@ import {
type ImageInput,
type ImageRequestFor,
type ImageRoute,
} from "../image"
import { Auth, type Definition as AuthDefinition } from "../route/auth"
} from "../image.js"
import { Auth, type Definition as AuthDefinition } from "../route/auth.js"
import {
InvalidProviderOutputReason,
AIError,
@@ -16,10 +16,10 @@ import {
mergeHttpOptions,
mergeJsonRecords,
type HttpOptions,
} from "../schema"
import { ProviderShared } from "./shared"
import { ImageInputs } from "./utils/image-input"
import { OpenAIImage } from "./utils/openai-image"
} from "../schema/index.js"
import { ProviderShared } from "./shared.js"
import { ImageInputs } from "./utils/image-input.js"
import { OpenAIImage } from "./utils/openai-image.js"
const ADAPTER = "openai-images"
export const DEFAULT_BASE_URL = "https://api.openai.com/v1"
+12 -12
View File
@@ -1,15 +1,15 @@
import { Effect, Encoding, Schema } from "effect"
import { Route } from "../route/client"
import { Auth } from "../route/auth"
import { Endpoint } from "../route/endpoint"
import { Protocol } from "../route/protocol"
import { HttpTransport, WebSocketTransport } from "../route/transport"
import { LLMEvent, LLMRequest, type JsonSchema, type ToolDefinition } from "../schema"
import { OpenResponses } from "./open-responses"
import { optionalArray, ProviderShared } from "./shared"
import { Lifecycle } from "./utils/lifecycle"
import { OpenAIImage } from "./utils/openai-image"
import { ToolSchemaProjection } from "./utils/tool-schema"
import { Route } from "../route/client.js"
import { Auth } from "../route/auth.js"
import { Endpoint } from "../route/endpoint.js"
import { Protocol } from "../route/protocol.js"
import { HttpTransport, WebSocketTransport } from "../route/transport/index.js"
import { LLMEvent, LLMRequest, type JsonSchema, type ToolDefinition } from "../schema/index.js"
import { OpenResponses } from "./open-responses.js"
import { optionalArray, ProviderShared } from "./shared.js"
import { Lifecycle } from "./utils/lifecycle.js"
import { OpenAIImage } from "./utils/openai-image.js"
import { ToolSchemaProjection } from "./utils/tool-schema.js"
const ADAPTER = "openai-responses"
const NAME = "OpenAI Responses"
@@ -290,4 +290,4 @@ export const webSocketRoute = Route.make({
defaults: { providerOptions: { openai: { store: false } } },
})
export * as OpenAIResponses from "./openai-responses"
export * as OpenAIResponses from "./openai-responses.js"
+3 -3
View File
@@ -12,8 +12,8 @@ import {
type MediaPart,
type TextPart,
type ToolResultPart,
} from "../schema"
import { isRecord } from "../utils/record"
} from "../schema/index.js"
import { isRecord } from "../utils/record.js"
export { isRecord }
export const Json = Schema.fromJsonString(Schema.Unknown)
@@ -324,4 +324,4 @@ export const jsonPost = (input: { readonly url: string; readonly body: string; r
HttpClientRequest.bodyText(input.body, "application/json"),
)
export * as ProviderShared from "./shared"
export * as ProviderShared from "./shared.js"
@@ -1,8 +1,8 @@
import { AwsV4Signer } from "aws4fetch"
import { Effect } from "effect"
import { Headers } from "effect/unstable/http"
import { Auth, type AuthInput } from "../../route/auth"
import { ProviderShared } from "../shared"
import { Auth, type AuthInput } from "../../route/auth.js"
import { ProviderShared } from "../shared.js"
/**
* AWS credentials for SigV4 signing. Bedrock also supports Bearer API key auth,
@@ -74,4 +74,4 @@ export const sigV4 = (
/** Bedrock route auth defaults to SigV4 and expects credentials from route configuration. */
export const auth = sigV4(undefined)
export * as BedrockAuth from "./bedrock-auth"
export * as BedrockAuth from "./bedrock-auth.js"
@@ -1,6 +1,6 @@
import { Schema } from "effect"
import type { CacheHint } from "../../schema"
import { newBreakpoints, ttlBucket, type Breakpoints } from "./cache"
import type { CacheHint } from "../../schema/index.js"
import { newBreakpoints, ttlBucket, type Breakpoints } from "./cache.js"
// Bedrock cache markers are positional: emit a `cachePoint` block immediately
// after the content the caller wants treated as a cacheable prefix. Bedrock
@@ -18,7 +18,7 @@ export type CachePointBlock = Schema.Schema.Type<typeof CachePointBlock>
// budget is respected across `system`, `messages`, and `tools`.
export const BEDROCK_BREAKPOINT_CAP = 4
export type { Breakpoints } from "./cache"
export type { Breakpoints } from "./cache.js"
export const breakpoints = () => newBreakpoints(BEDROCK_BREAKPOINT_CAP)
const DEFAULT_5M: CachePointBlock = { cachePoint: { type: "default" } }
@@ -34,4 +34,4 @@ export const block = (breakpoints: Breakpoints, cache: CacheHint | undefined): C
return ttlBucket(cache.ttlSeconds) === "1h" ? DEFAULT_1H : DEFAULT_5M
}
export * as BedrockCache from "./bedrock-cache"
export * as BedrockCache from "./bedrock-cache.js"
@@ -1,6 +1,6 @@
import { Effect, Schema } from "effect"
import type { MediaPart } from "../../schema"
import { ProviderShared } from "../shared"
import type { MediaPart } from "../../schema/index.js"
import { ProviderShared } from "../shared.js"
// Bedrock Converse accepts image `format` as the file extension and
// `source.bytes` as base64 in the JSON wire format.
@@ -89,4 +89,4 @@ export const lower = Effect.fn("BedrockMedia.lower")(function* (part: MediaPart)
return yield* ProviderShared.invalidRequest(`Bedrock Converse does not support media type ${part.mediaType}`)
})
export * as BedrockMedia from "./bedrock-media"
export * as BedrockMedia from "./bedrock-media.js"
@@ -1,4 +1,4 @@
import { isRecord } from "../../utils/record"
import { isRecord } from "../../utils/record.js"
// Gemini accepts a JSON Schema-like dialect for tool parameters, but rejects a
// handful of common JSON Schema shapes. Keep this projection isolated so the
@@ -116,4 +116,4 @@ const projectNode = (schema: unknown, nested = false): Record<string, unknown> |
export const convert = (schema: unknown) => projectNode(sanitizeNode(schema))
export * as GeminiToolSchema from "./gemini-tool-schema"
export * as GeminiToolSchema from "./gemini-tool-schema.js"
@@ -1,6 +1,6 @@
import { Effect, Encoding } from "effect"
import type { ImageInput } from "../../image"
import { InvalidRequestReason, AIError } from "../../schema"
import type { ImageInput } from "../../image.js"
import { InvalidRequestReason, AIError } from "../../schema/index.js"
const invalid = (module: string, message: string) =>
new AIError({
+2 -2
View File
@@ -1,4 +1,4 @@
import { LLMEvent, type FinishReasonDetails, type ProviderMetadata, type Usage } from "../../schema"
import { LLMEvent, type FinishReasonDetails, type ProviderMetadata, type Usage } from "../../schema/index.js"
export interface State {
readonly stepStarted: boolean
@@ -102,4 +102,4 @@ export const finish = (
return { ...stepped, stepStarted: false }
}
export * as Lifecycle from "./lifecycle"
export * as Lifecycle from "./lifecycle.js"
@@ -1,5 +1,5 @@
import { Schema } from "effect"
import { TextVerbosity, type LLMRequest } from "../../schema"
import { TextVerbosity, type LLMRequest } from "../../schema/index.js"
export const ResponseIncludables = [
"file_search_call.results",
@@ -60,4 +60,4 @@ export const resolve = (request: LLMRequest): Resolved => {
}
}
export * as OpenResponsesOptions from "./open-responses-options"
export * as OpenResponsesOptions from "./open-responses-options.js"
@@ -1,5 +1,5 @@
import { ReasoningEfforts } from "../../schema"
import { OpenResponsesOptions } from "./open-responses-options"
import { ReasoningEfforts } from "../../schema/index.js"
import { OpenResponsesOptions } from "./open-responses-options.js"
export const OpenAIReasoningEfforts = ReasoningEfforts
export type OpenAIReasoningEffort = string
@@ -20,4 +20,4 @@ export const isReasoningEffort = (effort: unknown): effort is OpenAIReasoningEff
export const resolve = OpenResponsesOptions.resolve
export * as OpenAIOptions from "./openai-options"
export * as OpenAIOptions from "./openai-options.js"
@@ -1,6 +1,6 @@
import type { JsonSchema, LanguageModelToolSchemaCompatibility } from "../../schema"
import { isRecord } from "../../utils/record"
import { GeminiToolSchema } from "./gemini-tool-schema"
import type { JsonSchema, LanguageModelToolSchemaCompatibility } from "../../schema/index.js"
import { isRecord } from "../../utils/record.js"
import { GeminiToolSchema } from "./gemini-tool-schema.js"
const removeNullSchemas = (value: unknown): unknown => {
if (Array.isArray(value)) return value.map(removeNullSchemas)
@@ -1,6 +1,6 @@
import { Effect } from "effect"
import { AIError, LLMEvent, type ProviderMetadata, type ToolCall, type ToolInputError } from "../../schema"
import { eventError, parseToolInput, type ToolAccumulator } from "../shared"
import { AIError, LLMEvent, type ProviderMetadata, type ToolCall, type ToolInputError } from "../../schema/index.js"
import { eventError, parseToolInput, type ToolAccumulator } from "../shared.js"
type StreamKey = string | number
@@ -223,4 +223,4 @@ export const finishAll = <K extends StreamKey>(route: string, tools: State<K>) =
}
})
export * as ToolStream from "./tool-stream"
export * as ToolStream from "./tool-stream.js"
+5 -5
View File
@@ -1,7 +1,7 @@
import { Effect, Encoding, Schema } from "effect"
import { Headers, HttpClientRequest } from "effect/unstable/http"
import { GeneratedImage, ImageModel, ImageResponse, type ImageRequestFor, type ImageRoute } from "../image"
import { Auth, type Definition as AuthDefinition } from "../route/auth"
import { GeneratedImage, ImageModel, ImageResponse, type ImageRequestFor, type ImageRoute } from "../image.js"
import { Auth, type Definition as AuthDefinition } from "../route/auth.js"
import {
InvalidProviderOutputReason,
AIError,
@@ -9,9 +9,9 @@ import {
mergeHttpOptions,
mergeJsonRecords,
type HttpOptions,
} from "../schema"
import { ProviderShared, optionalNull } from "./shared"
import { ImageInputs } from "./utils/image-input"
} from "../schema/index.js"
import { ProviderShared, optionalNull } from "./shared.js"
import { ImageInputs } from "./utils/image-input.js"
const ADAPTER = "xai-images"
export const DEFAULT_BASE_URL = "https://api.x.ai/v1"
+11 -5
View File
@@ -1,10 +1,16 @@
import { Effect, Schema } from "effect"
import { Headers, HttpClientRequest } from "effect/unstable/http"
import { GeneratedImage, ImageModel, ImageResponse, type ImageRequestFor, type ImageRoute } from "../image"
import { Auth, type Definition as AuthDefinition } from "../route/auth"
import { InvalidProviderOutputReason, AIError, mergeHttpOptions, mergeJsonRecords, type HttpOptions } from "../schema"
import { ProviderShared } from "./shared"
import { ImageInputs } from "./utils/image-input"
import { GeneratedImage, ImageModel, ImageResponse, type ImageRequestFor, type ImageRoute } from "../image.js"
import { Auth, type Definition as AuthDefinition } from "../route/auth.js"
import {
InvalidProviderOutputReason,
AIError,
mergeHttpOptions,
mergeJsonRecords,
type HttpOptions,
} from "../schema/index.js"
import { ProviderShared } from "./shared.js"
import { ImageInputs } from "./utils/image-input.js"
const ADAPTER = "zai-images"
export const DEFAULT_BASE_URL = "https://api.z.ai/api/paas/v4"
+1 -1
View File
@@ -12,7 +12,7 @@ import {
type HttpContext,
type HttpRateLimitDetails,
type ProviderMetadata,
} from "./schema"
} from "./schema/index.js"
const patterns = [
/prompt is too long/i,
+2 -2
View File
@@ -1,4 +1,4 @@
import type { LanguageModel, ProviderOptions } from "./schema"
import type { LanguageModel, ProviderOptions } from "./schema/index.js"
export interface Settings extends Readonly<Record<string, unknown>> {
readonly baseURL?: string
@@ -18,4 +18,4 @@ export interface Definition<
readonly model: (modelID: string, settings: ProviderSettings) => LanguageModel<Options>
}
export * as ProviderPackage from "./provider-package"
export * as ProviderPackage from "./provider-package.js"
+2 -2
View File
@@ -1,4 +1,4 @@
import type { LanguageModel, ModelID, ProviderID } from "./schema"
import type { LanguageModel, ModelID, ProviderID } from "./schema/index.js"
export type LanguageModelOptions = Pick<LanguageModel.Input, "defaults" | "compatibility">
@@ -33,4 +33,4 @@ export const make = <DefinitionType extends DefinitionShape>(
definition: NoExtraFields<DefinitionType, DefinitionShape>,
) => definition
export * as Provider from "./provider"
export * as Provider from "./provider.js"
+1 -1
View File
@@ -1 +1 @@
export * from "./providers/index"
export * from "./providers/index.js"
@@ -1,11 +1,11 @@
import { Auth } from "../route/auth"
import type { Route as RouteDef, RouteDefaultsInput } from "../route/client"
import type { ProviderPackage } from "../provider-package"
import { OpenAIChat } from "../protocols/openai-chat"
import { OpenAIResponses } from "../protocols/openai-responses"
import { BedrockAuth, type Credentials } from "../protocols/utils/bedrock-auth"
import { ProviderID, type ModelID } from "../schema"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options"
import { Auth } from "../route/auth.js"
import type { Route as RouteDef, RouteDefaultsInput } from "../route/client.js"
import type { ProviderPackage } from "../provider-package.js"
import { OpenAIChat } from "../protocols/openai-chat.js"
import { OpenAIResponses } from "../protocols/openai-responses.js"
import { BedrockAuth, type Credentials } from "../protocols/utils/bedrock-auth.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options.js"
export const id = ProviderID.make("amazon-bedrock")
+6 -6
View File
@@ -1,9 +1,9 @@
import type { RouteDefaultsInput } from "../route/client"
import { Auth } from "../route/auth"
import type { ProviderPackage } from "../provider-package"
import { ProviderID, type ModelID } from "../schema"
import * as BedrockConverse from "../protocols/bedrock-converse"
import type { BedrockCredentials } from "../protocols/bedrock-converse"
import type { RouteDefaultsInput } from "../route/client.js"
import { Auth } from "../route/auth.js"
import type { ProviderPackage } from "../provider-package.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import * as BedrockConverse from "../protocols/bedrock-converse.js"
import type { BedrockCredentials } from "../protocols/bedrock-converse.js"
export const id = ProviderID.make("amazon-bedrock")
@@ -1,2 +1,2 @@
export { chatModel as model } from "../amazon-bedrock-mantle"
export type { Settings } from "../amazon-bedrock-mantle"
export { chatModel as model } from "../amazon-bedrock-mantle.js"
export type { Settings } from "../amazon-bedrock-mantle.js"
@@ -1,2 +1,2 @@
export { chatModel as model } from "../../amazon-bedrock-mantle"
export type { Settings } from "../../amazon-bedrock-mantle"
export { chatModel as model } from "../../amazon-bedrock-mantle.js"
export type { Settings } from "../../amazon-bedrock-mantle.js"
@@ -1,2 +1,2 @@
export { responsesModel as model } from "../../amazon-bedrock-mantle"
export type { Settings } from "../../amazon-bedrock-mantle"
export { responsesModel as model } from "../../amazon-bedrock-mantle.js"
export type { Settings } from "../../amazon-bedrock-mantle.js"
@@ -1,9 +1,9 @@
import type { ProviderPackage } from "../provider-package"
import { AnthropicMessages } from "../protocols/anthropic-messages"
import { Auth } from "../route/auth"
import type { ProviderAuthOption } from "../route/auth-options"
import type { RouteDefaultsInput } from "../route/client"
import { ProviderID, type ModelID } from "../schema"
import type { ProviderPackage } from "../provider-package.js"
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
import { Auth } from "../route/auth.js"
import type { ProviderAuthOption } from "../route/auth-options.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { ProviderID, type ModelID } from "../schema/index.js"
export type AnthropicOptionsInput = AnthropicMessages.OptionsInput
export type AnthropicProviderOptionsInput = AnthropicMessages.ProviderOptionsInput
@@ -74,4 +74,4 @@ export const model: ProviderPackage.Definition<Settings, AnthropicMessages.Provi
}).model(modelID)
}
export * as AnthropicCompatible from "./anthropic-compatible"
export * as AnthropicCompatible from "./anthropic-compatible.js"
+7 -7
View File
@@ -1,10 +1,10 @@
import type { RouteDefaultsInput } from "../route/client"
import { Auth } from "../route/auth"
import type { ProviderAuthOption } from "../route/auth-options"
import type { ProviderPackage } from "../provider-package"
import { ProviderID, type ModelID } from "../schema"
import { AnthropicMessages } from "../protocols/anthropic-messages"
import { AnthropicCompatible } from "./anthropic-compatible"
import type { RouteDefaultsInput } from "../route/client.js"
import { Auth } from "../route/auth.js"
import type { ProviderAuthOption } from "../route/auth-options.js"
import type { ProviderPackage } from "../provider-package.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
import { AnthropicCompatible } from "./anthropic-compatible.js"
export type AnthropicOptionsInput = AnthropicMessages.OptionsInput
export type AnthropicProviderOptionsInput = AnthropicMessages.ProviderOptionsInput
+9 -9
View File
@@ -1,12 +1,12 @@
import { Auth } from "../route/auth"
import { type AtLeastOne, type ProviderAuthOption } from "../route/auth-options"
import type { Route as RouteDef, RouteDefaultsInput } from "../route/client"
import type { ProviderPackage } from "../provider-package"
import { ProviderID, type ModelID } from "../schema"
import * as OpenAIChat from "../protocols/openai-chat"
import * as OpenAIResponses from "../protocols/openai-responses"
import { ProviderShared } from "../protocols/shared"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options"
import { Auth } from "../route/auth.js"
import { type AtLeastOne, type ProviderAuthOption } from "../route/auth-options.js"
import type { Route as RouteDef, RouteDefaultsInput } from "../route/client.js"
import type { ProviderPackage } from "../provider-package.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import * as OpenAIChat from "../protocols/openai-chat.js"
import * as OpenAIResponses from "../protocols/openai-responses.js"
import { ProviderShared } from "../protocols/shared.js"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options.js"
export const id = ProviderID.make("azure")
const routeAuth = Auth.remove("authorization")
+2 -2
View File
@@ -1,2 +1,2 @@
export { chatModel as model } from "../azure"
export type { Settings } from "../azure"
export { chatModel as model } from "../azure.js"
export type { Settings } from "../azure.js"
+2 -2
View File
@@ -1,2 +1,2 @@
export { responsesModel as model } from "../azure"
export type { Settings } from "../azure"
export { responsesModel as model } from "../azure.js"
export type { Settings } from "../azure.js"
+6 -6
View File
@@ -1,10 +1,10 @@
import type { Config, Redacted } from "effect"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat"
import { Auth } from "../route/auth"
import { AuthOptions, type AtLeastOne, type ProviderAuthOption } from "../route/auth-options"
import type { RouteDefaultsInput } from "../route/client"
import { ProviderID, type ModelID } from "../schema"
import type { OpenAIProviderOptionsInput } from "./openai-options"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat.js"
import { Auth } from "../route/auth.js"
import { AuthOptions, type AtLeastOne, type ProviderAuthOption } from "../route/auth-options.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import type { OpenAIProviderOptionsInput } from "./openai-options.js"
export const aiGatewayID = ProviderID.make("cloudflare-ai-gateway")
export const workersAIID = ProviderID.make("cloudflare-workers-ai")
@@ -1,9 +1,9 @@
import type { ProviderPackage } from "../provider-package"
import { OpenAICompatibleChat } from "../protocols/openai-compatible-chat"
import type { RouteDefaultsInput } from "../route/client"
import { ProviderID, type ModelID } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
import type { OpenAIProviderOptionsInput } from "./openai-options"
import type { ProviderPackage } from "../provider-package.js"
import { OpenAICompatibleChat } from "../protocols/openai-compatible-chat.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { GoogleVertexShared } from "./google-vertex-shared.js"
import type { OpenAIProviderOptionsInput } from "./openai-options.js"
export const id = ProviderID.make("google-vertex")
@@ -1,13 +1,13 @@
import { Effect, Schema, Struct } from "effect"
import type { ProviderPackage } from "../provider-package"
import { AnthropicMessages } from "../protocols/anthropic-messages"
import { Auth } from "../route/auth"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
import { ProviderID, type ModelID } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
import type { ProviderPackage } from "../provider-package.js"
import { AnthropicMessages } from "../protocols/anthropic-messages.js"
import { Auth } from "../route/auth.js"
import { Route, type RouteDefaultsInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { Framing } from "../route/framing.js"
import { Protocol } from "../route/protocol.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { GoogleVertexShared } from "./google-vertex-shared.js"
export type AnthropicOptionsInput = AnthropicMessages.OptionsInput
export type AnthropicProviderOptionsInput = AnthropicMessages.ProviderOptionsInput
@@ -1,9 +1,9 @@
import type { ProviderPackage } from "../provider-package"
import { OpenAICompatibleResponses } from "../protocols/openai-compatible-responses"
import type { RouteDefaultsInput } from "../route/client"
import { ProviderID, type ModelID } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options"
import type { ProviderPackage } from "../provider-package.js"
import { OpenAICompatibleResponses } from "../protocols/openai-compatible-responses.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { GoogleVertexShared } from "./google-vertex-shared.js"
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js"
export const id = ProviderID.make("google-vertex")
@@ -1,6 +1,6 @@
import type { AnyAuthClient } from "google-auth-library"
import { Effect, Redacted } from "effect"
import { Auth, MissingCredentialError } from "../route/auth"
import { Auth, MissingCredentialError } from "../route/auth.js"
const SCOPE = "https://www.googleapis.com/auth/cloud-platform"
@@ -74,4 +74,4 @@ export const oauth = (input: OAuthOptions, project?: string) => {
return adc(project)
}
export * as GoogleVertexShared from "./google-vertex-shared"
export * as GoogleVertexShared from "./google-vertex-shared.js"
+8 -8
View File
@@ -1,11 +1,11 @@
import type { ProviderPackage } from "../provider-package"
import { Gemini } from "../protocols/gemini"
import { Auth } from "../route/auth"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { ProviderID, type ModelID } from "../schema"
import { GoogleVertexShared } from "./google-vertex-shared"
import type { ProviderPackage } from "../provider-package.js"
import { Gemini } from "../protocols/gemini.js"
import { Auth } from "../route/auth.js"
import { Route, type RouteDefaultsInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { Framing } from "../route/framing.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import { GoogleVertexShared } from "./google-vertex-shared.js"
export type GeminiOptionsInput = Gemini.OptionsInput
export type GeminiProviderOptionsInput = Gemini.ProviderOptionsInput
@@ -1,2 +1,2 @@
export { model } from "../google-vertex-chat"
export type { Settings } from "../google-vertex-chat"
export { model } from "../google-vertex-chat.js"
export type { Settings } from "../google-vertex-chat.js"
@@ -1,2 +1,2 @@
export { model } from "../google-vertex"
export type { Settings } from "../google-vertex"
export { model } from "../google-vertex.js"
export type { Settings } from "../google-vertex.js"
@@ -1,2 +1,2 @@
export { model } from "../google-vertex-messages"
export type { Settings } from "../google-vertex-messages"
export { model } from "../google-vertex-messages.js"
export type { Settings } from "../google-vertex-messages.js"
@@ -1,2 +1,2 @@
export { model } from "../google-vertex-responses"
export type { Settings } from "../google-vertex-responses"
export { model } from "../google-vertex-responses.js"
export type { Settings } from "../google-vertex-responses.js"
+8 -8
View File
@@ -1,12 +1,12 @@
import type { RouteDefaultsInput } from "../route/client"
import { Auth } from "../route/auth"
import type { ProviderAuthOption } from "../route/auth-options"
import type { ProviderPackage } from "../provider-package"
import { HttpOptions, ProviderID, mergeHttpOptions, type ModelID } from "../schema"
import { Gemini } from "../protocols/gemini"
import { GoogleImages } from "../protocols/google-images"
import type { RouteDefaultsInput } from "../route/client.js"
import { Auth } from "../route/auth.js"
import type { ProviderAuthOption } from "../route/auth-options.js"
import type { ProviderPackage } from "../provider-package.js"
import { HttpOptions, ProviderID, mergeHttpOptions, type ModelID } from "../schema/index.js"
import { Gemini } from "../protocols/gemini.js"
import { GoogleImages } from "../protocols/google-images.js"
export type { GoogleImageOptions } from "../protocols/google-images"
export type { GoogleImageOptions } from "../protocols/google-images.js"
export type GeminiOptionsInput = Gemini.OptionsInput
export type GeminiProviderOptionsInput = Gemini.ProviderOptionsInput
+18 -18
View File
@@ -1,18 +1,18 @@
export * as Anthropic from "./anthropic"
export * as AnthropicCompatible from "./anthropic-compatible"
export * as AmazonBedrock from "./amazon-bedrock"
export * as AmazonBedrockMantle from "./amazon-bedrock-mantle"
export * as Azure from "./azure"
export * as Cloudflare from "./cloudflare"
export { CloudflareAIGateway, CloudflareWorkersAI } from "./cloudflare"
export * as Google from "./google"
export * as GoogleVertex from "./google-vertex"
export * as GoogleVertexChat from "./google-vertex-chat"
export * as GoogleVertexMessages from "./google-vertex-messages"
export * as GoogleVertexResponses from "./google-vertex-responses"
export * as OpenAI from "./openai"
export * as OpenAICompatible from "./openai-compatible"
export * as OpenAICompatibleResponses from "./openai-compatible-responses"
export * as OpenRouter from "./openrouter"
export * as XAI from "./xai"
export * as ZAI from "./zai"
export * as Anthropic from "./anthropic.js"
export * as AnthropicCompatible from "./anthropic-compatible.js"
export * as AmazonBedrock from "./amazon-bedrock.js"
export * as AmazonBedrockMantle from "./amazon-bedrock-mantle.js"
export * as Azure from "./azure.js"
export * as Cloudflare from "./cloudflare.js"
export { CloudflareAIGateway, CloudflareWorkersAI } from "./cloudflare.js"
export * as Google from "./google.js"
export * as GoogleVertex from "./google-vertex.js"
export * as GoogleVertexChat from "./google-vertex-chat.js"
export * as GoogleVertexMessages from "./google-vertex-messages.js"
export * as GoogleVertexResponses from "./google-vertex-responses.js"
export * as OpenAI from "./openai.js"
export * as OpenAICompatible from "./openai-compatible.js"
export * as OpenAICompatibleResponses from "./openai-compatible-responses.js"
export * as OpenRouter from "./openrouter.js"
export * as XAI from "./xai.js"
export * as ZAI from "./zai.js"
@@ -1,5 +1,5 @@
import type { ResponseIncludable, ServiceTier } from "../protocols/utils/open-responses-options"
import type { ProviderOptions, ReasoningEffort, TextVerbosity } from "../schema"
import type { ResponseIncludable, ServiceTier } from "../protocols/utils/open-responses-options.js"
import type { ProviderOptions, ReasoningEffort, TextVerbosity } from "../schema/index.js"
export interface OpenResponsesOptionsInput {
readonly [key: string]: unknown
@@ -16,4 +16,4 @@ export type OpenResponsesProviderOptionsInput = ProviderOptions & {
readonly openresponses?: OpenResponsesOptionsInput
}
export * as OpenResponsesProviderOptions from "./open-responses-options"
export * as OpenResponsesProviderOptions from "./open-responses-options.js"
@@ -1,11 +1,11 @@
import type { ProviderPackage } from "../provider-package"
import { OpenAICompatibleResponses } from "../protocols/openai-compatible-responses"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import type { RouteDefaultsInput } from "../route/client"
import { ProviderID, type ModelID } from "../schema"
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options"
import type { ProviderPackage } from "../provider-package.js"
import { OpenAICompatibleResponses } from "../protocols/openai-compatible-responses.js"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { ProviderID, type ModelID } from "../schema/index.js"
import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js"
export type { OpenResponsesOptionsInput, OpenResponsesProviderOptionsInput } from "./open-responses-options"
export type { OpenResponsesOptionsInput, OpenResponsesProviderOptionsInput } from "./open-responses-options.js"
export const id = ProviderID.make("openai-compatible")
@@ -1,10 +1,10 @@
import { ProviderID, type ModelID } from "../schema"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat"
import type { RouteDefaultsInput } from "../route/client"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import type { ProviderPackage } from "../provider-package"
import { profiles, type OpenAICompatibleProfile } from "./openai-compatible-profile"
import type { OpenAIProviderOptionsInput } from "./openai-options"
import { ProviderID, type ModelID } from "../schema/index.js"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat.js"
import type { RouteDefaultsInput } from "../route/client.js"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import type { ProviderPackage } from "../provider-package.js"
import { profiles, type OpenAICompatibleProfile } from "./openai-compatible-profile.js"
import type { OpenAIProviderOptionsInput } from "./openai-options.js"
export const id = ProviderID.make("openai-compatible")
@@ -1 +1 @@
export * from "../openai-compatible-responses"
export * from "../openai-compatible-responses.js"
+5 -5
View File
@@ -1,8 +1,8 @@
import type { ProviderOptions } from "../schema"
import { mergeProviderOptions } from "../schema"
import type { OpenResponsesOptionsInput } from "./open-responses-options"
import type { ProviderOptions } from "../schema/index.js"
import { mergeProviderOptions } from "../schema/index.js"
import type { OpenResponsesOptionsInput } from "./open-responses-options.js"
export type { OpenAIResponseIncludable, OpenAIServiceTier } from "../protocols/utils/openai-options"
export type { OpenAIResponseIncludable, OpenAIServiceTier } from "../protocols/utils/openai-options.js"
export type OpenAIOptionsInput = OpenResponsesOptionsInput
@@ -67,4 +67,4 @@ export const withOpenAIOptions = <Options extends { readonly providerOptions?: O
}
}
export * as OpenAIProviderOptions from "./openai-options"
export * as OpenAIProviderOptions from "./openai-options.js"
+10 -10
View File
@@ -1,14 +1,14 @@
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import type { Route, RouteDefaultsInput } from "../route/client"
import type { ProviderPackage } from "../provider-package"
import { HttpOptions, ProviderID, ToolDefinition, mergeHttpOptions, type ModelID } from "../schema"
import * as OpenAIChat from "../protocols/openai-chat"
import * as OpenAIResponses from "../protocols/openai-responses"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options"
import { OpenAIImages, type OpenAIImageString } from "../protocols/openai-images"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import type { Route, RouteDefaultsInput } from "../route/client.js"
import type { ProviderPackage } from "../provider-package.js"
import { HttpOptions, ProviderID, ToolDefinition, mergeHttpOptions, type ModelID } from "../schema/index.js"
import * as OpenAIChat from "../protocols/openai-chat.js"
import * as OpenAIResponses from "../protocols/openai-responses.js"
import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options.js"
import { OpenAIImages, type OpenAIImageString } from "../protocols/openai-images.js"
export type { OpenAIOptionsInput, OpenAIResponseIncludable } from "./openai-options"
export type { OpenAIImageOptions } from "../protocols/openai-images"
export type { OpenAIOptionsInput, OpenAIResponseIncludable } from "./openai-options.js"
export type { OpenAIImageOptions } from "../protocols/openai-images.js"
export const id = ProviderID.make("openai")
+2 -2
View File
@@ -1,2 +1,2 @@
export { chatModel as model } from "../openai"
export type { Settings } from "../openai"
export { chatModel as model } from "../openai.js"
export type { Settings } from "../openai.js"
@@ -1,2 +1,2 @@
export { model } from "../openai"
export type { Settings } from "../openai"
export { model } from "../openai.js"
export type { Settings } from "../openai.js"
+11 -11
View File
@@ -1,15 +1,15 @@
import { Effect, Schema } from "effect"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { Framing } from "../route/framing"
import { Protocol } from "../route/protocol"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import { ProviderID, type CacheHint, type ModelID, type ProviderOptions } from "../schema"
import type { ProviderPackage } from "../provider-package"
import * as OpenAICompatibleProfiles from "./openai-compatible-profile"
import * as OpenAIChat from "../protocols/openai-chat"
import { newBreakpoints, ttlBucket } from "../protocols/utils/cache"
import { isRecord } from "../protocols/shared"
import { Route, type RouteDefaultsInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { Framing } from "../route/framing.js"
import { Protocol } from "../route/protocol.js"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import { ProviderID, type CacheHint, type ModelID, type ProviderOptions } from "../schema/index.js"
import type { ProviderPackage } from "../provider-package.js"
import * as OpenAICompatibleProfiles from "./openai-compatible-profile.js"
import * as OpenAIChat from "../protocols/openai-chat.js"
import { newBreakpoints, ttlBucket } from "../protocols/utils/cache.js"
import { isRecord } from "../protocols/shared.js"
export const profile = OpenAICompatibleProfiles.profiles.openrouter
export const id = ProviderID.make(profile.provider)
+12 -12
View File
@@ -1,14 +1,14 @@
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import { Route, type RouteDefaultsInput } from "../route/client"
import { Endpoint } from "../route/endpoint"
import { HttpOptions, ProviderID, type ModelID, type ProviderOptions } from "../schema"
import * as OpenAICompatibleProfiles from "./openai-compatible-profile"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat"
import * as OpenAIChat from "../protocols/openai-chat"
import * as OpenAIResponses from "../protocols/openai-responses"
import { XAIImages } from "../protocols/xai-images"
import type { OpenAIOptionsInput } from "./openai-options"
import type { ProviderPackage } from "../provider-package"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import { Route, type RouteDefaultsInput } from "../route/client.js"
import { Endpoint } from "../route/endpoint.js"
import { HttpOptions, ProviderID, type ModelID, type ProviderOptions } from "../schema/index.js"
import * as OpenAICompatibleProfiles from "./openai-compatible-profile.js"
import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat.js"
import * as OpenAIChat from "../protocols/openai-chat.js"
import * as OpenAIResponses from "../protocols/openai-responses.js"
import { XAIImages } from "../protocols/xai-images.js"
import type { OpenAIOptionsInput } from "./openai-options.js"
import type { ProviderPackage } from "../provider-package.js"
export const id = ProviderID.make("xai")
@@ -28,7 +28,7 @@ export interface Settings extends ProviderPackage.Settings {
readonly providerOptions?: XAIProviderOptionsInput
}
export type { XAIImageOptions } from "../protocols/xai-images"
export type { XAIImageOptions } from "../protocols/xai-images.js"
const responsesRoute = Route.make({
id: "openai-responses",
+4 -4
View File
@@ -1,6 +1,6 @@
import { ZAIImages } from "../protocols/zai-images"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
import { HttpOptions, ProviderID, type ModelID } from "../schema"
import { ZAIImages } from "../protocols/zai-images.js"
import { AuthOptions, type ProviderAuthOption } from "../route/auth-options.js"
import { HttpOptions, ProviderID, type ModelID } from "../schema/index.js"
export const id = ProviderID.make("zai")
@@ -10,7 +10,7 @@ export type Config = ProviderAuthOption<"optional"> & {
readonly http?: HttpOptions.Input
}
export type { ZAIImageOptions } from "../protocols/zai-images"
export type { ZAIImageOptions } from "../protocols/zai-images.js"
const auth = (options: ProviderAuthOption<"optional">) => AuthOptions.bearer(options, "ZAI_API_KEY")
+1 -1
View File
@@ -1 +1 @@
export * from "./route/index"
export * from "./route/index.js"
+2 -2
View File
@@ -1,5 +1,5 @@
import type { Config, Redacted } from "effect"
import { Auth } from "./auth"
import { Auth } from "./auth.js"
export type ApiKeyMode = "optional" | "required"
@@ -61,4 +61,4 @@ export const bearer = (
.bearer()
}
export * as AuthOptions from "./auth-options"
export * as AuthOptions from "./auth-options.js"
+2 -2
View File
@@ -1,6 +1,6 @@
import { Config, Effect, Redacted } from "effect"
import { Headers } from "effect/unstable/http"
import { AuthenticationReason, InvalidRequestReason, AIError, type HttpOptions } from "../schema"
import { AuthenticationReason, InvalidRequestReason, AIError, type HttpOptions } from "../schema/index.js"
export class MissingCredentialError extends Error {
readonly _tag = "MissingCredentialError"
@@ -153,4 +153,4 @@ export const toEffect =
(authInput: AuthInput): Effect.Effect<Headers.Headers, AIError> =>
input.apply(authInput).pipe(Effect.mapError(toAIError))
export * as Auth from "./auth"
export * as Auth from "./auth.js"
+12 -12
View File
@@ -1,16 +1,16 @@
import { Cause, Context, Effect, Layer, Schema, Stream } from "effect"
import * as Option from "effect/Option"
import { Auth } from "./auth"
import { Endpoint, type EndpointPatch } from "./endpoint"
import { RequestExecutor } from "./executor"
import { Framing } from "./framing"
import { HttpTransport } from "./transport"
import type { HttpMiddleware, Transport, TransportRuntime } from "./transport"
import { WebSocketExecutor } from "./transport"
import type { Protocol } from "./protocol"
import { applyCachePolicy } from "../cache-policy"
import * as ProviderShared from "../protocols/shared"
import type { ProtocolID, ProviderOptions } from "../schema"
import { Auth } from "./auth.js"
import { Endpoint, type EndpointPatch } from "./endpoint.js"
import { RequestExecutor } from "./executor.js"
import { Framing } from "./framing.js"
import { HttpTransport } from "./transport/index.js"
import type { HttpMiddleware, Transport, TransportRuntime } from "./transport/index.js"
import { WebSocketExecutor } from "./transport/index.js"
import type { Protocol } from "./protocol.js"
import { applyCachePolicy } from "../cache-policy.js"
import * as ProviderShared from "../protocols/shared.js"
import type { ProtocolID, ProviderOptions } from "../schema/index.js"
import {
AIError,
GenerationOptions,
@@ -25,7 +25,7 @@ import {
mergeGenerationOptions,
mergeHttpOptions,
mergeProviderOptions,
} from "../schema"
} from "../schema/index.js"
export interface RouteBody<Body> {
/** Schema for the validated provider-native body sent as the JSON request. */
+3 -3
View File
@@ -1,5 +1,5 @@
import type { LLMRequest } from "../schema"
import * as ProviderShared from "../protocols/shared"
import type { LLMRequest } from "../schema/index.js"
import * as ProviderShared from "../protocols/shared.js"
export interface EndpointInput<Body> {
readonly request: LLMRequest
@@ -53,4 +53,4 @@ export const render = <Body>(endpoint: Definition<Body>, input: EndpointInput<Bo
return url
}
export * as Endpoint from "./endpoint"
export * as Endpoint from "./endpoint.js"
+117 -38
View File
@@ -1,4 +1,4 @@
import { Cause, Context, Effect, Layer, Option, Schema } from "effect"
import { Cause, Context, Effect, Layer, Option, Schema, Stream } from "effect"
import {
FetchHttpClient,
Headers,
@@ -14,8 +14,8 @@ import {
HttpResponseDetails,
AIError,
TransportReason,
} from "../schema"
import { classifyProviderFailure } from "../provider-error"
} from "../schema/index.js"
import { classifyProviderFailure } from "../provider-error.js"
export interface Interface {
readonly execute: (
@@ -185,15 +185,15 @@ const secretValues = (request: HttpClientRequest.HttpClientRequest) => {
// Two passes: structural (redact `"name": "value"` and `name=value` patterns
// for any field name that looks sensitive) plus literal (replace any actual
// secret values we sent in the request, in case the response echoes one back).
const redactBody = (body: string, request: HttpClientRequest.HttpClientRequest) =>
Array.from(secretValues(request)).reduce(
const redactBody = (body: string, secrets: ReadonlySet<string>) =>
Array.from(secrets).reduce(
(text, secret) => text.split(secret).join(REDACTED),
body.replace(REDACT_JSON_FIELD, `$1"${REDACTED}"`).replace(REDACT_QUERY_FIELD, `$1${REDACTED}`),
)
const responseBody = (body: string | void, request: HttpClientRequest.HttpClientRequest) => {
const responseBody = (body: string | void, secrets: ReadonlySet<string>) => {
if (body === undefined) return {}
const redacted = redactBody(body, request)
const redacted = redactBody(body, secrets)
if (redacted.length <= BODY_LIMIT) return { body: redacted }
return { body: redacted.slice(0, BODY_LIMIT), bodyTruncated: true }
}
@@ -240,7 +240,7 @@ const statusError =
const headers = normalizedHeaders(response.headers)
const retryAfter = retryAfterMs(headers)
const rateLimit = rateLimitDetails(headers, retryAfter)
const details = responseBody(body, request)
const details = responseBody(body, secretValues(request))
return yield* new AIError({
module: "RequestExecutor",
method: "execute",
@@ -261,44 +261,122 @@ const statusError =
})
})
const toHttpError = (redactedNames: ReadonlyArray<string | RegExp>) => (error: unknown) => {
const transportError = (input: {
readonly message: string
readonly kind?: string | undefined
readonly request?: HttpClientRequest.HttpClientRequest | undefined
}) =>
// Classifies an HTTP failure captured outside the executor (for example by the
// AI SDK's own fetch) onto the same reason types and redacted HttpContext that
// executor-driven requests produce. The originating request is not available on
// that path, so the method is assumed (language model calls are always POST),
// request headers are empty, and only structural body redaction applies.
export const classifyHttpFailure = (input: {
readonly message: string
readonly url: string
readonly status?: number | undefined
readonly code?: string | undefined
readonly responseHeaders?: Record<string, string> | undefined
readonly responseBody?: string | undefined
}) => {
const headers = normalizedHeaders(Headers.fromInput(input.responseHeaders))
const retryAfter = retryAfterMs(headers)
const rateLimit = rateLimitDetails(headers, retryAfter)
const details = responseBody(input.responseBody ?? undefined, new Set<string>())
return classifyProviderFailure({
message: input.message,
status: input.status,
code: input.code,
retryAfterMs: retryAfter,
rateLimit,
http: new HttpContext({
request: new HttpRequestDetails({ method: "POST", url: redactUrl(input.url), headers: {} }),
response:
input.status === undefined
? undefined
: new HttpResponseDetails({ status: input.status, headers: redactHeaders(Headers.fromInput(headers), []) }),
...details,
requestId: requestId(headers),
rateLimit,
}),
})
}
type HttpOperation = "request" | "read"
const NativeTransportFailure = Schema.Struct({
message: Schema.String,
code: Schema.optionalKey(Schema.String),
cause: Schema.optionalKey(Schema.Unknown),
})
const decodeNativeTransportFailure = Schema.decodeUnknownOption(NativeTransportFailure)
const nativeTransportFailure = (error: unknown) => {
const failure = Option.getOrUndefined(decodeNativeTransportFailure(error))
if (!failure) return undefined
if (failure.code !== undefined) return failure
const cause = Option.getOrUndefined(decodeNativeTransportFailure(failure.cause))
if (cause?.code !== undefined) return cause
return failure
}
const httpError = (input: {
readonly error: unknown
readonly request: HttpClientRequest.HttpClientRequest
readonly operation: HttpOperation
readonly redactedNames: ReadonlyArray<string | RegExp>
}) => {
const request = HttpClientError.isHttpClientError(input.error) ? input.error.request : input.request
const transportError = (failure: { readonly message: string; readonly code?: string | undefined }) =>
new AIError({
module: "RequestExecutor",
method: "execute",
method: input.operation,
reason: new TransportReason({
message: input.message,
kind: input.kind,
url: input.request ? redactUrl(input.request.url) : undefined,
http: input.request ? new HttpContext({ request: requestDetails(input.request, redactedNames) }) : undefined,
message: failure.message,
transport: "http",
operation: input.operation,
code: failure.code,
url: redactUrl(request.url),
http: new HttpContext({ request: requestDetails(request, input.redactedNames) }),
}),
})
if (Cause.isTimeoutError(error)) {
return transportError({ message: error.message, kind: "Timeout" })
}
if (!HttpClientError.isHttpClientError(error)) {
return transportError({ message: error instanceof Error ? error.message : "HTTP transport failed" })
}
const request = "request" in error ? error.request : undefined
if (error.reason._tag === "TransportError") {
const source =
HttpClientError.isHttpClientError(input.error) && "cause" in input.error.reason
? input.error.reason.cause
: input.error
const native = nativeTransportFailure(source)
const code = native?.code
const raw = native?.message ?? (input.error instanceof Error ? input.error.message : undefined)
const detail = raw ? redactBody(raw, secretValues(request)) : undefined
const message = code && detail && !detail.includes(code) ? `${code}: ${detail}` : detail
if (Cause.isTimeoutError(input.error) || Cause.isTimeoutError(source))
return transportError({ message: message ?? "HTTP transport timed out", code: code ?? "Timeout" })
if (!HttpClientError.isHttpClientError(input.error))
return transportError({ message: message ?? "HTTP transport failed", code })
if (input.error.reason._tag === "TransportError") {
return transportError({
message: error.reason.description ?? "HTTP transport failed",
kind: error.reason._tag,
request,
message: message ?? input.error.reason.description ?? "HTTP transport failed",
code: code ?? input.error.reason._tag,
})
}
return transportError({
message: `HTTP transport failed: ${error.reason._tag}`,
kind: error.reason._tag,
request,
message: message ?? `HTTP transport failed: ${input.error.reason._tag}`,
code: code ?? input.error.reason._tag,
})
}
export const stream = (
executor: Interface,
request: HttpClientRequest.HttpClientRequest,
middleware?: HttpMiddleware,
): Stream.Stream<Uint8Array, AIError> =>
Stream.unwrap(
Effect.gen(function* () {
const redactedNames = yield* Headers.CurrentRedactedNames
const response = yield* executor.execute(request, middleware)
return response.stream.pipe(
Stream.mapError((error) => httpError({ error, request: response.request, operation: "read", redactedNames })),
)
}),
)
export const layer: Layer.Layer<Service, never, HttpClient.HttpClient> = Layer.effect(
Service,
Effect.gen(function* () {
@@ -307,15 +385,16 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient> = Layer.e
Effect.gen(function* () {
const redactedNames = yield* Headers.CurrentRedactedNames
if (!middleware)
return yield* http
.execute(request)
.pipe(Effect.mapError(toHttpError(redactedNames)), Effect.flatMap(statusError(request, redactedNames)))
return yield* http.execute(request).pipe(
Effect.mapError((error) => httpError({ error, request, operation: "request", redactedNames })),
Effect.flatMap(statusError(request, redactedNames)),
)
const response = yield* middleware(request, (input) =>
http
.execute(input)
.pipe(Effect.mapError((cause) => (cause instanceof Error ? cause : new Error(String(cause))))),
).pipe(Effect.mapError(toHttpError(redactedNames)))
).pipe(Effect.mapError((error) => httpError({ error, request, operation: "request", redactedNames })))
return yield* statusError(response.request, redactedNames)(response)
})
return Service.of({
@@ -326,4 +405,4 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient> = Layer.e
export const fetchLayer = layer.pipe(Layer.provide(FetchHttpClient.layer))
export * as RequestExecutor from "./executor"
export * as RequestExecutor from "./executor.js"
+3 -3
View File
@@ -1,6 +1,6 @@
import type { Stream } from "effect"
import * as ProviderShared from "../protocols/shared"
import type { AIError } from "../schema"
import * as ProviderShared from "../protocols/shared.js"
import type { AIError } from "../schema/index.js"
/**
* Decode a streaming HTTP response body into provider-protocol frames.
@@ -24,4 +24,4 @@ export interface Definition<Frame> {
/** Server-Sent Events framing. Used by every JSON-streaming HTTP provider. */
export const sse: Definition<string> = { id: "sse", frame: ProviderShared.sseFraming }
export * as Framing from "./framing"
export * as Framing from "./framing.js"
+16 -16
View File
@@ -1,4 +1,4 @@
export { Route, LLMClient } from "./client"
export { Route, LLMClient } from "./client.js"
export type {
Route as RouteShape,
RouteLanguageModelInput,
@@ -9,18 +9,18 @@ export type {
Interface as LLMClientShape,
Service as LLMClientService,
StreamOptions,
} from "./client"
export * from "./executor"
export { Auth } from "./auth"
export { AuthOptions } from "./auth-options"
export { Endpoint } from "./endpoint"
export { Framing } from "./framing"
export { Protocol } from "./protocol"
export { HttpTransport, WebSocketExecutor, WebSocketTransport } from "./transport"
export * as Transport from "./transport"
export type { Definition as AuthShape, AuthInput, Credential, CredentialError } from "./auth"
export type { ApiKeyMode, AuthOverride, ProviderAuthOption } from "./auth-options"
export type { Definition as EndpointFn, EndpointInput } from "./endpoint"
export type { Definition as FramingDef } from "./framing"
export type { Protocol as ProtocolDef } from "./protocol"
export type { HttpHandler, HttpMiddleware, Transport as TransportDef, TransportRuntime } from "./transport"
} from "./client.js"
export * from "./executor.js"
export { Auth } from "./auth.js"
export { AuthOptions } from "./auth-options.js"
export { Endpoint } from "./endpoint.js"
export { Framing } from "./framing.js"
export { Protocol } from "./protocol.js"
export { HttpTransport, WebSocketExecutor, WebSocketTransport } from "./transport/index.js"
export * as Transport from "./transport/index.js"
export type { Definition as AuthShape, AuthInput, Credential, CredentialError } from "./auth.js"
export type { ApiKeyMode, AuthOverride, ProviderAuthOption } from "./auth-options.js"
export type { Definition as EndpointFn, EndpointInput } from "./endpoint.js"
export type { Definition as FramingDef } from "./framing.js"
export type { Protocol as ProtocolDef } from "./protocol.js"
export type { HttpHandler, HttpMiddleware, Transport as TransportDef, TransportRuntime } from "./transport/index.js"
+2 -2
View File
@@ -1,5 +1,5 @@
import { Schema, type Effect } from "effect"
import type { AIError, LLMEvent, LLMRequest, ProtocolID } from "../schema"
import type { AIError, LLMEvent, LLMRequest, ProtocolID } from "../schema/index.js"
/**
* The semantic API contract of one model server family.
@@ -82,4 +82,4 @@ export const make = <Body, Frame, Event, State>(
export const jsonEvent = <const S extends Schema.Top>(schema: S) => Schema.fromJsonString(schema)
export * as Protocol from "./protocol"
export * as Protocol from "./protocol.js"
+10 -27
View File
@@ -1,11 +1,12 @@
import { Effect, Stream } from "effect"
import { Effect } from "effect"
import { Headers, HttpClientRequest } from "effect/unstable/http"
import { Auth } from "../auth"
import { render as renderEndpoint } from "../endpoint"
import { Framing } from "../framing"
import type { HttpMiddleware, Transport, TransportPrepareInput } from "./index"
import * as ProviderShared from "../../protocols/shared"
import { mergeJsonRecords, type LLMRequest } from "../../schema"
import { Auth } from "../auth.js"
import { render as renderEndpoint } from "../endpoint.js"
import { Framing } from "../framing.js"
import type { HttpMiddleware, Transport, TransportPrepareInput } from "./index.js"
import * as ProviderShared from "../../protocols/shared.js"
import { mergeJsonRecords, type LLMRequest } from "../../schema/index.js"
import { RequestExecutor } from "../executor.js"
export type JsonRequestInput<Body> = TransportPrepareInput<Body>
@@ -86,26 +87,8 @@ export const httpJson = <Body, Frame>(input: HttpJsonInput<Body, Frame>): HttpJs
middleware: prepareInput.middleware,
}
}),
frames: (prepared, request, runtime) =>
Stream.unwrap(
runtime.http
.execute(prepared.request, prepared.middleware)
.pipe(
Effect.map((response) =>
prepared.framing.frame(
response.stream.pipe(
Stream.mapError((error) =>
ProviderShared.eventError(
`${request.model.provider}/${request.model.route.id}`,
`Failed to read ${request.model.provider}/${request.model.route.id} stream`,
ProviderShared.errorText(error),
),
),
),
),
),
),
),
frames: (prepared, _request, runtime) =>
prepared.framing.frame(RequestExecutor.stream(runtime.http, prepared.request, prepared.middleware)),
})
export const sseJson = {
+8 -8
View File
@@ -1,9 +1,9 @@
import type { Effect, Stream } from "effect"
import { Endpoint } from "../endpoint"
import { Auth } from "../auth"
import type { HttpMiddleware, Interface as RequestExecutorInterface } from "../executor"
import type { Interface as WebSocketExecutorInterface } from "./websocket"
import type { AIError, LLMRequest } from "../../schema"
import { Endpoint } from "../endpoint.js"
import { Auth } from "../auth.js"
import type { HttpMiddleware, Interface as RequestExecutorInterface } from "../executor.js"
import type { Interface as WebSocketExecutorInterface } from "./websocket.js"
import type { AIError, LLMRequest } from "../../schema/index.js"
export interface TransportRuntime {
readonly http: RequestExecutorInterface
@@ -26,6 +26,6 @@ export interface TransportPrepareInput<Body> {
readonly middleware?: HttpMiddleware
}
export * as HttpTransport from "./http"
export type { HttpHandler, HttpMiddleware } from "../executor"
export { WebSocketExecutor, WebSocketTransport } from "./websocket"
export * as HttpTransport from "./http.js"
export type { HttpHandler, HttpMiddleware } from "../executor.js"
export { WebSocketExecutor, WebSocketTransport } from "./websocket.js"
+38 -15
View File
@@ -1,8 +1,8 @@
import { Cause, Context, Effect, Layer, Queue, Stream } from "effect"
import { Headers } from "effect/unstable/http"
import { AIError, TransportReason } from "../../schema"
import * as HttpTransport from "./http"
import type { Transport } from "./index"
import { AIError, TransportReason, type TransportOperation } from "../../schema/index.js"
import * as HttpTransport from "./http.js"
import type { Transport } from "./index.js"
export interface WebSocketRequest {
readonly url: string
@@ -29,12 +29,18 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/AI
const transportError = (
method: string,
message: string,
input: { readonly url?: string; readonly kind?: string } = {},
input: { readonly operation: TransportOperation; readonly url?: string; readonly code?: string },
) =>
new AIError({
module: "WebSocketExecutor",
method,
reason: new TransportReason({ message, url: input.url, kind: input.kind }),
reason: new TransportReason({
message,
transport: "websocket",
operation: input.operation,
url: input.url,
code: input.code,
}),
})
const eventMessage = (event: Event) => {
@@ -55,7 +61,8 @@ const waitOpen = (ws: globalThis.WebSocket, input: WebSocketRequest) => {
return Effect.fail(
transportError("open", `WebSocket closed before opening (state ${ws.readyState})`, {
url: input.url,
kind: "open",
operation: "request",
code: "closed",
}),
)
}
@@ -79,7 +86,10 @@ const waitOpen = (ws: globalThis.WebSocket, input: WebSocketRequest) => {
cleanup()
resume(
Effect.fail(
transportError("open", `Failed to open WebSocket: ${eventMessage(event)}`, { url: input.url, kind: "open" }),
transportError("open", `Failed to open WebSocket: ${eventMessage(event)}`, {
url: input.url,
operation: "request",
}),
),
)
}
@@ -89,7 +99,8 @@ const waitOpen = (ws: globalThis.WebSocket, input: WebSocketRequest) => {
Effect.fail(
transportError("open", `WebSocket closed before opening with code ${event.code}`, {
url: input.url,
kind: "open",
operation: "request",
code: String(event.code),
}),
),
)
@@ -118,7 +129,8 @@ const webSocketUrl = (value: string) =>
catch: (error) =>
transportError("prepare", error instanceof Error ? error.message : "Invalid WebSocket URL", {
url: value,
kind: "websocket",
operation: "request",
code: "invalid-url",
}),
})
@@ -129,7 +141,7 @@ export const open = (input: WebSocketRequest) =>
catch: (error) =>
transportError("open", error instanceof Error ? error.message : "Failed to construct WebSocket", {
url: input.url,
kind: "open",
operation: "request",
}),
}).pipe(Effect.flatMap((ws) => fromWebSocket(ws, input)))
@@ -150,7 +162,10 @@ export const fromWebSocket = (
Queue.failCauseUnsafe(
messages,
Cause.fail(
transportError("message", "Unsupported WebSocket message payload", { url: input.url, kind: "message" }),
transportError("message", "Unsupported WebSocket message payload", {
url: input.url,
operation: "read",
}),
),
)
}
@@ -158,7 +173,10 @@ export const fromWebSocket = (
Queue.failCauseUnsafe(
messages,
Cause.fail(
transportError("message", `WebSocket error: ${eventMessage(event)}`, { url: input.url, kind: "message" }),
transportError("message", `WebSocket error: ${eventMessage(event)}`, {
url: input.url,
operation: "read",
}),
),
)
}
@@ -167,7 +185,11 @@ export const fromWebSocket = (
Queue.failCauseUnsafe(
messages,
Cause.fail(
transportError("message", `WebSocket closed with code ${event.code}`, { url: input.url, kind: "close" }),
transportError("message", `WebSocket closed with code ${event.code}`, {
url: input.url,
operation: "read",
code: String(event.code),
}),
),
)
}
@@ -188,7 +210,7 @@ export const fromWebSocket = (
catch: (error) =>
transportError("sendText", error instanceof Error ? error.message : "Failed to send WebSocket message", {
url: input.url,
kind: "write",
operation: "write",
}),
}),
messages: Stream.fromQueue(messages),
@@ -243,7 +265,8 @@ export const json = <Body, Message>(input: JsonInput<Body, Message>): JsonTransp
return Stream.fail(
transportError("json", "WebSocket JSON transport requires WebSocketExecutor.Service", {
url: prepared.url,
kind: "websocket",
operation: "request",
code: "unavailable",
}),
)
}
+10 -2
View File
@@ -1,6 +1,6 @@
import { Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import { ModelID, ProviderID, ProviderMetadata, RouteID } from "./ids"
import { ModelID, ProviderID, ProviderMetadata, RouteID } from "./ids.js"
export const ProviderFailureClassification = Schema.Literals(["context-overflow", "payload-too-large"])
export type ProviderFailureClassification = typeof ProviderFailureClassification.Type
@@ -92,10 +92,18 @@ export class ProviderInternalReason extends Schema.Class<ProviderInternalReason>
http: Schema.optional(HttpContext),
}) {}
export const TransportType = Schema.Literals(["http", "websocket"])
export type TransportType = typeof TransportType.Type
export const TransportOperation = Schema.Literals(["request", "read", "write"])
export type TransportOperation = typeof TransportOperation.Type
export class TransportReason extends Schema.Class<TransportReason>("AI.Error.Transport")({
_tag: Schema.tag("Transport"),
message: Schema.String,
kind: Schema.optional(Schema.String),
transport: TransportType,
operation: TransportOperation,
code: Schema.optional(Schema.String),
url: Schema.optional(Schema.String),
http: Schema.optional(HttpContext),
}) {}
+3 -3
View File
@@ -1,7 +1,7 @@
import { Schema } from "effect"
import { ContentBlockID, FinishReason, ProviderMetadata, ToolCallID } from "./ids"
import { Message, ToolCallPart, ToolOutput, ToolResultPart, ToolResultValue, type ContentPart } from "./messages"
import { ProviderFailureClassification } from "./errors"
import { ContentBlockID, FinishReason, ProviderMetadata, ToolCallID } from "./ids.js"
import { Message, ToolCallPart, ToolOutput, ToolResultPart, ToolResultValue, type ContentPart } from "./messages.js"
import { ProviderFailureClassification } from "./errors.js"
/**
* Token usage reported by an LLM provider.
+5 -5
View File
@@ -1,5 +1,5 @@
export * from "./ids"
export * from "./options"
export * from "./messages"
export * from "./events"
export * from "./errors"
export * from "./ids.js"
export * from "./options.js"
export * from "./messages.js"
export * from "./events.js"
export * from "./errors.js"
+10 -3
View File
@@ -1,8 +1,15 @@
import { Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import { JsonSchema, MessageRole, ProviderMetadata } from "./ids"
import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, LanguageModelSchema, ProviderOptions } from "./options"
import { isRecord } from "../utils/record"
import { JsonSchema, MessageRole, ProviderMetadata } from "./ids.js"
import {
CacheHint,
CachePolicy,
GenerationOptions,
HttpOptions,
LanguageModelSchema,
ProviderOptions,
} from "./options.js"
import { isRecord } from "../utils/record.js"
const systemPartSchema = Schema.Struct({
type: Schema.Literal("text"),
+3 -3
View File
@@ -1,7 +1,7 @@
import { Schema } from "effect"
import { JsonSchema, ModelID, ProviderID } from "./ids"
import type { AnyRoute } from "../route/client"
import { isRecord } from "../utils/record"
import { JsonSchema, ModelID, ProviderID } from "./ids.js"
import type { AnyRoute } from "../route/client.js"
import { isRecord } from "../utils/record.js"
export const mergeJsonRecords = (
...items: ReadonlyArray<Record<string, unknown> | undefined>
+3 -3
View File
@@ -1,6 +1,6 @@
export * as TestLLM from "./testing"
export * as TestLLM from "./testing.js"
import { LLMClient, type Interface as LLMClientShape } from "./route/client"
import { LLMClient, type Interface as LLMClientShape } from "./route/client.js"
import {
LLMEvent,
LLMResponse,
@@ -8,7 +8,7 @@ import {
type AIError,
type LLMRequest,
type UsageInput,
} from "./schema"
} from "./schema/index.js"
import { Context, Deferred, Effect, Latch, Layer, Queue, Scope, Stream } from "effect"
export type Response = readonly LLMEvent[] | Stream.Stream<LLMEvent, AIError>
+2 -2
View File
@@ -7,8 +7,8 @@ import {
ToolResultValue,
type ToolOutput as ToolOutputType,
type ToolResultValue as ToolResultValueType,
} from "./schema"
import { type AnyTool, type Tools } from "./tool"
} from "./schema/index.js"
import { type AnyTool, type Tools } from "./tool.js"
export interface ToolSettlement {
readonly result: ToolResultValueType
+7 -3
View File
@@ -1,7 +1,11 @@
import { Effect, JsonSchema, Schema } from "effect"
import { Tool } from "@opencode-ai/schema/tool"
import type { ToolCallPart, ToolDefinition as ToolDefinitionClass, ToolOutput as ToolOutputType } from "./schema"
import { ToolDefinition, ToolFailure, ToolOutput } from "./schema"
import type {
ToolCallPart,
ToolDefinition as ToolDefinitionClass,
ToolOutput as ToolOutputType,
} from "./schema/index.js"
import { ToolDefinition, ToolFailure, ToolOutput } from "./schema/index.js"
/**
* Schema constraint for tool parameters / success values: no decoding or
@@ -245,4 +249,4 @@ const project = (
export { ToolFailure }
export * as Tool from "./tool"
export * as Tool from "./tool.js"

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