Compare commits

...

837 Commits

Author SHA1 Message Date
GitHub Action
5c503b9c70 chore: regen sdk 2025-12-09 17:02:25 +00:00
Aiden Cline
659f23de30 docs: ecosystem page 2025-12-09 11:01:48 -06:00
GitHub Action
2252b5ca1b chore: format code 2025-12-09 03:18:47 +00:00
terakael
c78dad8db5 tui: add permission indicator to footer (#4813)
Co-authored-by: terakael <terakael@gmail.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-08 21:18:17 -06:00
opencode
0569e8652c release: v1.0.137 2025-12-09 03:00:50 +00:00
GitHub Action
f2d5b32e52 chore: regen sdk 2025-12-09 02:17:38 +00:00
Matt Silverlock
b2f5ea7c30 themes: add new orng theme (#5267)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-08 20:17:10 -06:00
GitHub Action
8eb8f1a16c chore: format code 2025-12-09 02:07:00 +00:00
Aiden Cline
ad93d50ab7 ci: ignore 2025-12-08 20:06:27 -06:00
GitHub Action
73c5c328a8 chore: regen sdk 2025-12-09 01:07:23 +00:00
Dax Raad
72a13212e2 ci 2025-12-08 20:06:36 -05:00
Github Action
78bcf35f37 Update Nix flake.lock and hashes 2025-12-09 00:52:48 +00:00
GitHub Action
3a3ee3ecfd chore: format code 2025-12-09 00:52:05 +00:00
Sebastian Herrlinger
34e045c275 bump opentui to v0.1.59, allowing shift+space insert as char again 2025-12-09 01:51:27 +01:00
GitHub Action
e187918ce0 chore: regen sdk 2025-12-08 23:46:24 +00:00
Aiden Cline
7ac17c7833 ci: ignore 2025-12-08 17:45:50 -06:00
GitHub Action
b05d5b30fb chore: format code 2025-12-08 22:44:57 +00:00
Aiden Cline
57c08b01b7 ignore: mark ripgrep as an sst/tap/opencode depends_on 2025-12-08 16:42:32 -06:00
GitHub Action
08efb9cdf6 chore: regen sdk 2025-12-08 22:16:30 +00:00
Ariane Emory
8b51da768c fix: improve sidebar working directory colour contrast with modified files (resolves #5184 (#5188) 2025-12-08 16:15:40 -06:00
Github Action
862407c674 Update Nix flake.lock and hashes 2025-12-08 22:11:38 +00:00
GitHub Action
a381aa7e0d chore: format code 2025-12-08 22:10:46 +00:00
Aiden Cline
4dcda3d53d fix: parcel watcher musl support 2025-12-08 16:08:53 -06:00
GitHub Action
479cca29a5 chore: regen sdk 2025-12-08 21:29:05 +00:00
Ravi Kumar
e38814c597 fix: apply provider filtering to /connect endpoint (#5233) 2025-12-08 15:28:32 -06:00
GitHub Action
4d42daa9a3 chore: format code 2025-12-08 21:05:09 +00:00
Ariane Emory
130345bd5d fix: sort sessions by updated time (resolves #5074) (#5080) 2025-12-08 15:04:39 -06:00
Github Action
0baee00be4 Update Nix flake.lock and hashes 2025-12-08 21:00:43 +00:00
GitHub Action
e0acd5d361 chore: regen sdk 2025-12-08 20:59:55 +00:00
Sebastian Herrlinger
1e7d78a215 bump opentui to v0.1.58, fixing diff color issues in light themes 2025-12-08 21:59:09 +01:00
GitHub Action
7a6cb85617 chore: format code 2025-12-08 20:34:25 +00:00
Shoubhit Dash
20530104ce add ocaml lsp support (#5230) 2025-12-08 14:33:45 -06:00
GitHub Action
d22754dd68 chore: regen sdk 2025-12-08 20:06:51 +00:00
Sebastian Herrlinger
db0e1ebb80 fix colors for dialog prompt (like session rename prompt in light theme) 2025-12-08 21:06:03 +01:00
Sebastian Herrlinger
e83a47debe set theme text color for no matching items in auto complete 2025-12-08 20:59:00 +01:00
GitHub Action
eed48e76de chore: format code 2025-12-08 18:06:48 +00:00
Aiden Cline
ac70c1e813 docs: lsp & formatters 2025-12-08 12:05:25 -06:00
GitHub Action
ac0bed16a2 chore: regen sdk 2025-12-08 18:02:54 +00:00
rari404
fab8ab2840 feat: add terraform-ls language server and formatter (#5243) 2025-12-08 12:02:25 -06:00
GitHub Action
09ff8eba00 chore: format code 2025-12-08 17:40:24 +00:00
rari404
9bd2ea5e5f feat: add bash-language-server LSP (#5246) 2025-12-08 11:39:49 -06:00
GitHub Action
aa525482ae chore: regen sdk 2025-12-08 17:37:58 +00:00
Shoubhit Dash
285605737d add ocamlformat support (#5229) 2025-12-08 11:37:30 -06:00
GitHub Action
4201fe6e01 chore: format code 2025-12-08 17:31:56 +00:00
Daniel Polito
203f3312ee feat: ability to toggle MCP Servers in TUI (#4509) 2025-12-08 11:31:22 -06:00
GitHub Action
0c77c46dc7 chore: regen sdk 2025-12-08 17:28:14 +00:00
Jérôme Benoit
52bb43eebd fix: SAP AI Core Vercel AI SDK v2 support (#5180)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2025-12-08 11:27:47 -06:00
GitHub Action
e020f5355e chore: format code 2025-12-08 17:07:18 +00:00
rari404
9b86d4e595 feat: add theme support for thinking text opacity (#5240) 2025-12-08 11:06:46 -06:00
GitHub Action
f3d3b41a3f chore: regen sdk 2025-12-08 16:27:32 +00:00
Bishal Roy
a959199f09 feat: add catppuccin-macchiato theme (#5225) 2025-12-08 10:27:03 -06:00
Adam
5e3a59d5a2 feat: resize handle 2025-12-08 10:24:26 -06:00
Adam
9f23d85e20 wip(desktop): progress 2025-12-08 10:24:26 -06:00
GitHub Action
54e15b38ea chore: regen sdk 2025-12-08 15:48:52 +00:00
Adam
d66b903e7f fix: opencode web command 2025-12-08 09:48:21 -06:00
Adam
4425c66732 revert: opencode web command changes
This reverts commit c347056246.
2025-12-08 09:47:43 -06:00
GitHub Action
0dd0250285 chore: format code 2025-12-08 15:40:18 +00:00
Adam
c347056246 fix: opencode web command 2025-12-08 09:39:41 -06:00
GitHub Action
2a5255ac8f chore: regen sdk 2025-12-08 15:35:44 +00:00
Adam
d9175be989 fix: opencode web command 2025-12-08 09:35:12 -06:00
GitHub Action
cebbfcfbaa chore: format code 2025-12-08 15:19:26 +00:00
Adam
de415be4f6 fix: opencode web command 2025-12-08 09:18:46 -06:00
Adam
e8ce113b7f fix: bump localstorage 2025-12-08 09:05:26 -06:00
GitHub Action
8ca02b7664 chore: regen sdk 2025-12-08 12:48:30 +00:00
Adam
3f5bb21f16 chore: identity cleanup, vscode ext images 2025-12-08 06:47:57 -06:00
Github Action
fe114c41b5 Update Nix flake.lock and hashes 2025-12-08 12:25:44 +00:00
GitHub Action
d90fd8a5d7 chore: format code 2025-12-08 12:24:56 +00:00
Adam
9363c15b4a feat: better code and diff perf 2025-12-08 06:24:24 -06:00
GitHub Action
3325823f23 ignore: update download stats 2025-12-08 2025-12-08 12:04:36 +00:00
GitHub Action
4b4d8da1ad chore: regen sdk 2025-12-08 05:46:02 +00:00
Brendan Allan
d531dff8d3 Export DesktopInterface from desktop and add PlatformContext 2025-12-08 13:43:36 +08:00
GitHub Action
923bf36593 chore: format code 2025-12-08 04:54:08 +00:00
Justin Vogt
d6e499dd48 docs: Update "model" inheritance for agents (#4894)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-07 22:53:41 -06:00
GitHub Action
aec1497c6e chore: regen sdk 2025-12-08 04:43:13 +00:00
Aiden Cline
f5a77c8cd8 bump plugin versions 2025-12-07 22:42:35 -06:00
GitHub Action
bc524eeb44 chore: format code 2025-12-08 04:22:50 +00:00
ry2009
725f658260 fix: ensure Auth.all returns valid objs (#5128) 2025-12-07 22:22:21 -06:00
GitHub Action
af1080dd42 chore: regen sdk 2025-12-08 04:21:06 +00:00
Ariane Emory
63e54541fe fix: Sort themes in the /theme modal alphabetically (resolves #5217) (#5219)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-07 22:20:40 -06:00
GitHub Action
c3f7a88c1c chore: format code 2025-12-08 04:20:07 +00:00
opencode-agent[bot]
586a8b7b31 docs: azure content filter note (#5212)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-12-07 22:19:39 -06:00
GitHub Action
981744f802 chore: regen sdk 2025-12-08 03:54:26 +00:00
Aiden Cline
a3bb4a3c85 pdf support in read tool (#5222)
Co-authored-by: ammi1378 <ammi1378@users.noreply.github.com>
2025-12-07 21:54:00 -06:00
GitHub Action
06ba1f76dc chore: format code 2025-12-08 03:49:13 +00:00
Aiden Cline
076c8b2ca1 ci: fix fmt 2025-12-07 21:48:41 -06:00
Adam
9a90939ac4 fix: use diff context instead of prop drilling 2025-12-07 21:21:18 -06:00
GitHub Action
123a136093 chore: regen sdk 2025-12-08 02:56:09 +00:00
Dax Raad
4126fedbd4 openapi 2025-12-07 21:55:36 -05:00
Dax Raad
145d185e6f ci 2025-12-07 21:51:22 -05:00
GitHub Action
6b32667c7d chore: regen sdk 2025-12-08 02:29:26 +00:00
Aiden Cline
d8401e1937 ci: fix fmt 2025-12-07 20:28:50 -06:00
GitHub Action
55d6fcc350 chore: format code 2025-12-08 02:11:26 +00:00
Aiden Cline
9ff39503e9 tweak: additional error msg parsing case 2025-12-07 20:10:54 -06:00
GitHub Action
f96c181afd chore: regen sdk 2025-12-08 01:48:52 +00:00
Aiden Cline
f9b75a09df ignore: update description 2025-12-07 19:48:23 -06:00
GitHub Action
6111ed79b1 chore: format code 2025-12-08 01:47:31 +00:00
Ariane Emory
4cf2322b7f fix: toggle timestamps now properly hides/shows timestamps when toggled (resolves #5142) (#5145) 2025-12-07 19:47:02 -06:00
GitHub Action
2c6fcc5dc1 chore: regen sdk 2025-12-08 01:44:32 +00:00
franlol
81ee8541ab feat: add experimental.text.complete plugin hook (#4962) 2025-12-07 19:44:04 -06:00
GitHub Action
5b3550ab9f chore: format code 2025-12-08 01:13:22 +00:00
Patrick Erichsen
4fabce58d8 fix(cli): prevent help text wrapping (#5185) 2025-12-07 19:12:54 -06:00
GitHub Action
da7edb5f5c chore: regen sdk 2025-12-08 00:58:40 +00:00
Dax Raad
bf0f85e37f playing with sdk docs 2025-12-07 19:58:04 -05:00
Github Action
7b52160bff Update Nix flake.lock and hashes 2025-12-08 00:05:25 +00:00
GitHub Action
fde97ec4a7 chore: format code 2025-12-08 00:04:40 +00:00
Dax
ea7ec60f51 v2 SDK (#5216)
Co-authored-by: GitHub Action <action@github.com>
2025-12-07 19:04:14 -05:00
GitHub Action
6667856ba5 chore: format code 2025-12-07 20:53:12 +00:00
Dax Raad
13b2cf50ae remove outdated SDKs 2025-12-07 15:52:27 -05:00
Github Action
93b0abfce9 Update Nix flake.lock and hashes 2025-12-07 20:49:39 +00:00
GitHub Action
f7e4c47113 chore: regen sdk 2025-12-07 20:47:51 +00:00
André Cruz
509e43d6f8 feat(mcp): add OAuth authentication support for remote MCP servers (#5014) 2025-12-07 15:47:27 -05:00
GitHub Action
e693192e06 chore: regen sdk 2025-12-07 19:23:56 +00:00
rari404
ec27759f90 feat: add uninstall command (#5208) 2025-12-07 13:23:30 -06:00
GitHub Action
9c938eec73 chore: format code 2025-12-07 19:08:48 +00:00
secretninjaman
238b907dd8 fix: use basename for shell detection to support non-standard paths (#5205)
Co-authored-by: Ayato French <a@ayatofrench.com>
2025-12-07 13:08:26 -06:00
GitHub Action
c16d8c6db8 chore: format code 2025-12-07 19:06:37 +00:00
Aiden Cline
9856e3b798 ignore: add test for provider url case 2025-12-07 13:06:12 -06:00
GitHub Action
1d089272c8 chore: regen sdk 2025-12-07 19:01:34 +00:00
Aiden Cline
c30b1130ee fix: provider url merging logic 2025-12-07 13:01:05 -06:00
GitHub Action
40ca222d09 chore: format code 2025-12-07 18:48:45 +00:00
Dax Raad
0ecccbfd17 enable zoom hotkeys 2025-12-07 13:48:12 -05:00
GitHub Action
3f4862ced6 chore: regen sdk 2025-12-07 18:42:48 +00:00
Brendan Allan
1574e2457b Desktop macOS codesigning and notarization (#5154)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Dax Raad <d@ironbay.co>
2025-12-07 13:42:23 -05:00
GitHub Action
af33212f77 chore: format code 2025-12-07 18:26:05 +00:00
Mikheil Berishvili
4eb82e8c04 fix: autocomplete popup repositions on window resize (#5196) 2025-12-07 12:25:35 -06:00
GitHub Action
a45f0aac90 chore: regen sdk 2025-12-07 18:18:10 +00:00
Aiden Cline
eb4afdca65 ci: fix format 2025-12-07 12:17:40 -06:00
GitHub Action
9391749577 chore: format code 2025-12-07 15:33:51 +00:00
Carsten Kragelund Jørgensen
36a25660e9 fix: update zed agent server linux url to tar.gz (#5194) 2025-12-07 09:33:23 -06:00
GitHub Action
d9fe722da1 ignore: update download stats 2025-12-07 2025-12-07 12:04:11 +00:00
GitHub Action
da722e7db9 chore: regen sdk 2025-12-07 05:55:31 +00:00
Aiden Cline
75a4dcbce8 tweak: make bash give agent more awareness of cwd, bump default timeout, drop max timeout (#5140) 2025-12-06 23:55:07 -06:00
GitHub Action
3a179fcd34 chore: format code 2025-12-07 05:45:36 +00:00
Arindam Majumder
ad22fe9fe7 docs: Nebius Token Factory provider documentation (#2997) 2025-12-06 23:45:08 -06:00
GitHub Action
6d622d91be chore: regen sdk 2025-12-07 05:33:26 +00:00
Aiden Cline
aa884b003e core: prevent sessions from disappearing after git init
Previously, sessions created in a non-git directory would disappear from
the session picker after running git init and making the first commit.
This happened because the migration logic ran prematurely before a stable
project ID existed.
2025-12-06 23:32:47 -06:00
GitHub Action
e0f77940f9 chore: format code 2025-12-06 23:25:16 +00:00
Aiden Cline
3a1718f62b ci: fix review 2025-12-06 17:24:44 -06:00
GitHub Action
f7f9d3e5b9 chore: regen sdk 2025-12-06 23:23:24 +00:00
Dax Raad
68501d7799 ci 2025-12-06 18:22:55 -05:00
GitHub Action
f8a987b135 chore: format code 2025-12-06 23:22:04 +00:00
Dax Raad
dfea6780d9 sync 2025-12-06 18:21:32 -05:00
GitHub Action
2ac8dd6361 chore: regen sdk 2025-12-06 23:19:47 +00:00
Dax Raad
dd0945b9ca tui: add visual separator between username and timestamp for better readability 2025-12-06 18:19:18 -05:00
Dax Raad
1b05d5dd8e tui: prevent deprecated models from appearing in model picker 2025-12-06 18:18:45 -05:00
GitHub Action
6923cc4a6a chore: format code 2025-12-06 23:15:39 +00:00
Aiden Cline
3feb69e63c ci: fix format 2025-12-06 17:15:04 -06:00
GitHub Action
6723792fbb chore: regen sdk 2025-12-06 22:05:07 +00:00
Aiden Cline
3e36069f41 fix: reduce overhead of task tool metadata 2025-12-06 16:04:33 -06:00
GitHub Action
6a4ca92a6c chore: format code 2025-12-06 20:49:33 +00:00
Saatvik Arya
3ec34ee3dd feat(tui): add dynamic terminal window title (#5112) 2025-12-06 14:49:11 -06:00
GitHub Action
2e5c2d5e98 chore: regen sdk 2025-12-06 20:48:46 +00:00
Anchit Bajaj
4dbe17d4f1 fix: update description to lowercase for ACP command (to be consistent with other commands) (#5137) 2025-12-06 14:48:21 -06:00
GitHub Action
f18776cb49 chore: format code 2025-12-06 20:43:15 +00:00
Ariane Emory
429aa24275 fix: make timestamp toggle text dynamic in command list (resolves #5106) (#5108) 2025-12-06 14:42:46 -06:00
GitHub Action
741c9d3c63 chore: regen sdk 2025-12-06 20:30:00 +00:00
Ben Vargas
419983c0f1 feat: restore experimental flag for websearch/codesearch tools (#5132)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-06 14:29:34 -06:00
GitHub Action
a59c80e076 chore: format code 2025-12-06 20:28:25 +00:00
Cody Rayment
55981205da docs: update server API reference with complete endpoint list (#5136) 2025-12-06 14:28:02 -06:00
Dak Washbrook
c1e6037bda feat: add mercury.com theme (#5141) 2025-12-06 14:27:56 -06:00
Github Action
8e816a9283 Update Nix flake.lock and hashes 2025-12-06 12:45:14 +00:00
GitHub Action
d165c6b15a chore: regen sdk 2025-12-06 12:44:22 +00:00
Adam
9111005165 fix: terminal serialization and isolation 2025-12-06 06:43:53 -06:00
GitHub Action
3ceac25fb5 ignore: update download stats 2025-12-06 2025-12-06 12:04:12 +00:00
GitHub Action
8ec771d5be chore: format code 2025-12-06 11:53:20 +00:00
Adam
659e5653bc fix: exclude dist 2025-12-06 05:52:47 -06:00
Adam
3ff6de261c chore: update tauri update pub key 2025-12-06 05:49:05 -06:00
GitHub Action
25dae77fcd chore: regen sdk 2025-12-06 01:21:17 +00:00
Dax Raad
68daadcb56 sync 2025-12-05 20:20:47 -05:00
GitHub Action
c9b1bb0285 chore: format code 2025-12-06 01:14:58 +00:00
Dax
ac5809e757 Documentation edits made through Mintlify web editor 2025-12-05 20:14:29 -05:00
Dax
0db209a636 Documentation edits made through Mintlify web editor 2025-12-05 20:14:10 -05:00
GitHub Action
6c65f4acd1 chore: regen sdk 2025-12-06 01:13:23 +00:00
Dax Raad
3d447e8b12 ci 2025-12-05 20:12:52 -05:00
Dax Raad
f8807144d4 openapi route 2025-12-05 20:11:01 -05:00
GitHub Action
ebb4c8a724 chore: format code 2025-12-06 01:09:36 +00:00
Dax Raad
893f232b2f openapi json 2025-12-05 20:07:24 -05:00
GitHub Action
a6aaf5429c chore: format code 2025-12-06 01:02:41 +00:00
Dax Raad
4ef239a086 openapi generate 2025-12-05 20:01:55 -05:00
David Hill
9362368fd3 fix: add extra line break to install page 2025-12-05 23:43:26 +00:00
Adam
b35e010e2a feat: consistent (updated) social share images 2025-12-05 15:42:19 -06:00
GitHub Action
cc35e6a019 chore: format code 2025-12-05 21:42:15 +00:00
Dax Raad
3281888160 ignore: docs test 2025-12-05 16:41:35 -05:00
GitHub Action
c6d0ae892e chore: regen sdk 2025-12-05 21:02:17 +00:00
Aiden Cline
df67ae9cbe ci: regen sdk instead of failing tests 2025-12-05 15:01:41 -06:00
GitHub Action
ebe20efb29 chore: format code 2025-12-05 20:50:13 +00:00
franlol
b03b9b9017 feat: add optional scrollbar to the session chat (#5116)
Co-authored-by: Sebastian <hasta84@gmail.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-05 14:49:05 -06:00
opencode
73258c6193 release: v1.0.134 2025-12-05 20:46:49 +00:00
Github Action
dfe3fb8ed3 Update Nix flake.lock and hashes 2025-12-05 20:41:00 +00:00
Brendan Allan
cd6bfb3f69 OpenCode Desktop app (#5044)
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
2025-12-05 14:39:49 -06:00
Shantur Rathore
ba417d80b1 tweak: bash tool improve output metadata for agent consumption, fix small timeout issue (#5131) 2025-12-05 13:56:56 -06:00
Nathan Thomas
40eb8b93e1 feat: add max steps for supervisor and sub-agents (#4062)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-05 12:26:44 -06:00
Adam
6e6bd1e171 fix(desktop): terminal cursor position 2025-12-05 12:05:30 -06:00
Adam
81ee2d2332 fix(desktop): prompting 2025-12-05 10:51:35 -06:00
Aiden Cline
85974e9acd ignore: regen sdk 2025-12-05 10:50:14 -06:00
Noam Bressler
864c098701 add experimental.open_telemetry config option to enable OTEL spans (#4978)
Co-authored-by: noamzbr <noamzbr@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-05 10:48:22 -06:00
Adam
cfbaf81ef8 fix(desktop): clone pty session on reconnect 2025-12-05 10:30:48 -06:00
Adam
87a791fdb9 fix(desktop): new session not selecting tab 2025-12-05 10:30:48 -06:00
Anthony Shew
ada7cca10d feat(theme): Vercel (#5119)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-05 10:01:20 -06:00
Julian Visser
52db0f23a6 fix: #5064 ProviderInitError github-copilot-enterprise (#5123) 2025-12-05 09:53:32 -06:00
Dax Raad
60388f7f03 do not use required pty for local dev 2025-12-05 10:39:44 -05:00
Frank
53ed1c912b Zen: add codex max 2025-12-05 09:05:00 -05:00
GitHub Action
5f7ab83de4 ignore: update download stats 2025-12-05 2025-12-05 12:04:29 +00:00
Aiden Cline
05d2f70529 ignore: tweak 2025-12-05 01:00:47 -06:00
Aiden Cline
f950de95ba fix: ensure projects that go from having no commits to having commits have sessions migrated (#5105)
Co-authored-by: GitHub Action <action@github.com>
2025-12-05 00:49:07 -06:00
Aiden Cline
a4e5a72c36 ci: keybinds 2025-12-05 00:22:28 -06:00
ry2009
03324d4277 tui: wrap dialog option descriptions (#5083) 2025-12-05 00:19:48 -06:00
Aiden Cline
e53580cb68 ignore: cmd tweak 2025-12-05 00:11:47 -06:00
GitHub Action
332ebe36c3 chore: format code 2025-12-05 05:14:21 +00:00
Aiden Cline
5013d64b28 ignore: rm slop commnand (only for opencode repo this isnt shipping) 2025-12-04 23:13:41 -06:00
Aiden Cline
767a81f930 fix: ensure that vcs is still set to git even if no commits in repo 2025-12-04 23:02:11 -06:00
Aiden Cline
78046dac8b ci: review 2025-12-04 23:02:11 -06:00
Dax Raad
95168b8267 increase default scroll speed 2025-12-04 23:54:46 -05:00
Dax Raad
c264e9c364 fix 2025-12-04 23:48:32 -05:00
Dax Raad
856e1e2948 fix pty builds 2025-12-04 23:47:57 -05:00
Jérôme Benoit
bef4fdfc4b fix: add getModel to SAP AI Core provider for correct SDK initialization (#5086)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2025-12-04 22:43:22 -06:00
opencode-agent[bot]
095a1ab041 docs: llama.cpp docs: limit moved under model (#5089)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-12-04 22:39:13 -06:00
Dax Raad
71e578eac9 ignore: fix provider credentials query for BYOK
Provider credentials field was being selected from ProviderTable even when the table wasn't joined (when byokProvider was undefined). Now the join is conditional - when byokProvider exists, we join and get the credentials; when it doesn't, the join condition is always false so provider remains null.
2025-12-04 22:57:39 -05:00
Frank
4380727727 zen: fix byok 2025-12-04 21:53:33 -05:00
Github Action
392d46933b Update Nix flake.lock and hashes 2025-12-05 02:33:39 +00:00
GitHub Action
2bc0b46ff4 chore: format code 2025-12-05 02:33:01 +00:00
Adam
09f522f0aa Reapply "feat(desktop): terminal pane (#5081)"
This reverts commit f9dcd97936.
2025-12-04 20:32:08 -06:00
Github Action
d82bd430f6 Update Nix flake.lock and hashes 2025-12-04 22:02:17 +00:00
opencode
49800a00bd release: v1.0.133 2025-12-04 22:02:17 +00:00
Aiden Cline
f9dcd97936 Revert "feat(desktop): terminal pane (#5081)"
This reverts commit d763c11a6d.
2025-12-04 15:57:01 -06:00
Adam
d763c11a6d feat(desktop): terminal pane (#5081)
Co-authored-by: Github Action <action@github.com>
Co-authored-by: Dax Raad <d@ironbay.co>
2025-12-04 15:37:29 -06:00
Dax Raad
b1202ac6db core: add test for custom model npm package inheritance 2025-12-04 16:30:54 -05:00
Aiden Cline
d469d7d441 tweak: bash tool description re commit stuff 2025-12-04 15:27:23 -06:00
Cason Adams
48dc520fb8 docs: add CodeCompanion.nvim integration instructions (#5079) 2025-12-04 14:49:51 -06:00
Dax Raad
668d5a76d5 core: ensure model npm package falls back to dev models config when not explicitly defined 2025-12-04 15:39:52 -05:00
Jérôme Benoit
b9c1f10016 feat: Add SAP AI Core provider support (#5023)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2025-12-04 14:07:23 -06:00
Aiden Cline
8a0c86cbdb bump: builtin plugin versions 2025-12-04 12:37:14 -06:00
Daniel Polito
7f86fe3f61 add optional prompt Input to Github Action (#4828)
Co-authored-by: Github Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
2025-12-04 12:10:56 -06:00
Aiden Cline
a32cf70d7e tui: fix /new slash command being persisted in prompt input 2025-12-04 12:01:13 -06:00
Shantur Rathore
a607f33552 tweak: bash tool messages regarding timeouts and truncation more clear for agent (#5066) 2025-12-04 11:33:00 -06:00
Aiden Cline
350a32274a fix: model not being passed correctly to tool 2025-12-04 11:15:30 -06:00
Daniel Gray
27c99b46cb Preserve prompt input when creating new session (#4993) 2025-12-04 11:12:58 -06:00
Adam
1d6e3d477b fix(tui): cursor color 2025-12-04 06:56:48 -06:00
GitHub Action
efbb973393 ignore: update download stats 2025-12-04 2025-12-04 12:04:38 +00:00
Aiden Cline
45bc7a6a9d ci: cleaner 2025-12-04 01:14:09 -06:00
Aiden Cline
088ebb967f ci: only maintainer can trigger 2025-12-04 01:07:04 -06:00
Frank
bcf740f98a zen: make session provider sticky 2025-12-03 23:33:46 -05:00
wsx99outlook
6b80fff2bb ci: use blacksmith runners in review workflow too (#5042) 2025-12-03 22:30:00 -06:00
GitHub Action
2e63fedb76 chore: format code 2025-12-04 04:29:03 +00:00
YeonGyu-Kim
5a9f4e5c60 fix: ensure checkUpgrade sets init: (#5040) 2025-12-03 22:28:35 -06:00
opencode
d0a48a09e2 release: v1.0.132 2025-12-04 04:23:39 +00:00
GitHub Action
c0a21e7025 chore: format code 2025-12-04 04:19:15 +00:00
Dax Raad
10cc15aabe fix anthropic api key error 2025-12-03 23:18:24 -05:00
opencode
adf7681100 release: v1.0.131 2025-12-04 04:11:48 +00:00
Aiden Cline
0237905b96 fix: TypeError: undefined is not an object 2025-12-03 22:03:42 -06:00
GitHub Action
e8aa79bab6 chore: format code 2025-12-04 03:42:08 +00:00
Frank
4ff5783e59 zen: fix chart loading 2025-12-03 22:41:31 -05:00
opencode
dcfeb52983 release: v1.0.130 2025-12-04 03:38:18 +00:00
Jakub Matjanowski
46790e57e9 feat: Enhance DeepSeek reasoning content handling (#4975)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-12-03 21:31:36 -06:00
Jack Bisceglia
4bc3fa0826 docs: remove outdated theme section as system theme is now added back (#5041) 2025-12-03 21:10:26 -06:00
Aiden Cline
88cfb979be ci: add note about iife 2025-12-03 21:08:12 -06:00
Aiden Cline
32b5db754e fix: provider id issue 2025-12-03 20:45:55 -06:00
Aiden Cline
f33f8ca109 fix: compaction type issue 2025-12-03 20:43:47 -06:00
Aiden Cline
598d63db63 fix: dax typo 2025-12-03 20:39:11 -06:00
Github Action
38bff1b372 Update Nix flake.lock and hashes 2025-12-04 02:34:26 +00:00
Aiden Cline
e8c9b21f20 bump opentui 2025-12-03 20:33:08 -06:00
Dax
6d3fc63658 core: refactor provider and model system (#5033)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: thdxr <thdxr@users.noreply.github.com>
2025-12-03 21:09:03 -05:00
Dax Raad
ee4437ff32 core: add provider test coverage for upcoming refactor
Add comprehensive test suite for Provider module to ensure safe
refactoring of provider internals. Tests cover:
- Provider loading from env vars and config
- Provider filtering (disabled_providers, enabled_providers)
- Model whitelist/blacklist
- Model aliasing and custom providers
- getModel, getProvider, closest, defaultModel functions

Also adds Env module for instance-scoped environment variable access,
enabling isolated test environments without global state pollution.
2025-12-03 18:30:42 -05:00
Frank
7a4aa68706 zen: fix chart loading
closes #5030
2025-12-03 18:12:28 -05:00
Aiden Cline
f00380d285 ci: review tweak 2025-12-03 16:16:08 -06:00
Ariane Emory
c00d4885c6 feat: add tool_details keybind w/ no default (#4976)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-03 13:38:09 -06:00
Aiden Cline
70f4722356 ci: review ready for review action 2025-12-03 13:35:49 -06:00
Aiden Cline
8898bf7ca4 ci: tweak review cmd 2025-12-03 13:34:45 -06:00
Frank
e5b13b767e zen: usage graph respect light/dark mode 2025-12-03 14:24:44 -05:00
Aiden Cline
3181c68cbb ci: make review only fire on non draft pr creation 2025-12-03 13:10:40 -06:00
Aiden Cline
c3c9003dbb ci: add pr review 2025-12-03 12:45:06 -06:00
Ariane Emory
921b98066d feat: add messages_last_user command to scroll TUI to last user message (implements #4847) (#4855)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-03 12:30:11 -06:00
Luke Parker
c5b4cc80cc fix: bunfs path on windows (#5011) 2025-12-03 11:21:13 -06:00
Spoon
0bccd1d578 feat: experimental.primary_tools, allow user to set the tools that should only be available to primary agents (#4913)
Co-authored-by: GitHub Action <action@github.com>
2025-12-03 11:19:43 -06:00
Aiden Cline
91db82c138 add retry case for grok resource exhausted 2025-12-03 11:16:27 -06:00
GitHub Action
0eb97086fc chore: format code 2025-12-03 16:47:25 +00:00
Aiden Cline
5b34636afa ignore: docs & style 2025-12-03 10:46:48 -06:00
GitHub Action
f1138b9a55 ignore: update download stats 2025-12-03 2025-12-03 12:04:36 +00:00
opencode
23ff6dbba4 release: v1.0.129 2025-12-03 11:39:04 +00:00
Aiden Cline
b457923970 core: fix GitHub Copilot Enterprise authentication failing with sdk.chat undefined error 2025-12-02 23:37:10 -06:00
Jason Cheatham
66e4a5a64e tweak: adjust light/dark theme toggle (#5007) 2025-12-02 23:03:24 -06:00
Ben Vargas
6c25e64658 fix: correct Provider type in chat.params plugin hook (#5003) 2025-12-02 22:50:21 -06:00
Jason Cheatham
f2fd0f8f00 fix: handle 0 in ANSI theme color definitions (#5009) 2025-12-02 22:42:30 -06:00
Frank
44cdde5422 zen: fix removing provider 2025-12-02 21:52:12 -05:00
Github Action
88235dc618 Update Nix flake.lock and hashes 2025-12-03 02:17:49 +00:00
Sebastian Herrlinger
4d2b671d7b actually bump opentui to v0.1.55
- fix scrollbox empty/blank last items at bottom
- fix should not insert chars with modifiers in input/textarea anymore
- do not wrap OSC4 palette sequences for tmux 3.6
2025-12-03 03:16:32 +01:00
Sebastian Herrlinger
8098031eac Revert "bump opentui to v0.1.55"
This reverts commit 80636fec43.
2025-12-03 03:14:08 +01:00
Github Action
74c882d9d0 Update Nix flake.lock and hashes 2025-12-03 02:06:35 +00:00
Sebastian Herrlinger
80636fec43 bump opentui to v0.1.55
- fix scrollbox empty/blank last items at bottom
- fix should not insert chars with modifiers in input/textarea anymore
- do not wrap OSC4 palette sequences for tmux 3.6
2025-12-03 03:03:52 +01:00
Aiden Cline
a8ad74aef3 add basic session list command 2025-12-02 19:24:05 -06:00
Aiden Cline
e2e2b7934e Make homebrew update check use homebrew registry version info 2025-12-02 17:43:33 -06:00
Frank
28c802f399 wip: zen 2025-12-02 18:36:15 -05:00
Dalton Alexandre
bcfa63aa4e fix: allow unignoring files in .ignore (#4814) 2025-12-02 17:15:12 -06:00
Jay V
d40feafb01 ignore: commands 2025-12-02 18:09:16 -05:00
Jay V
2a8473891b docs: replace deprecated opencode auth login command with /connect across all documentation
Users no longer need to exit the TUI to add providers - they can now use the /connect command directly in the terminal interface. Updated all provider setup instructions to use simplified format with /connect command instead of the deprecated opencode auth login CLI command. Added /connect to TUI commands reference and streamlined provider documentation to show clearer, more concise setup steps.
2025-12-02 18:08:39 -05:00
Aiden Cline
a4e3451d5c tweak: make message border match color of agent it was sent to 2025-12-02 16:59:31 -06:00
Aiden Cline
53a7c2885b bump default lsp server timeout 2025-12-02 16:04:08 -06:00
Adam
f354507d42 fix: session turn margins 2025-12-02 15:50:24 -06:00
Jaga Santagostino
f17e1def32 toggle to hide username in TUI (#4750)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-02 15:11:03 -06:00
GitHub Action
3183e8b7d4 chore: format code 2025-12-02 20:28:17 +00:00
Aiden Cline
9d2b9ef2d4 ci: dont forget our european designer 2025-12-02 14:27:41 -06:00
opencode-agent[bot]
733e5cd876 add OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT (#4996)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-02 20:14:23 +00:00
opencode
4ee4f7bcb3 release: v1.0.128 2025-12-02 20:14:22 +00:00
GitHub Action
da7ecda9ea chore: format code 2025-12-02 19:52:47 +00:00
Frank
1f11d4fb1a zen: data dumper 2025-12-02 14:51:27 -05:00
Adam
b308503ab5 chore: remove comment (redeploy) 2025-12-02 13:49:48 -06:00
Adam
3b10de4a28 fix: vite config 2025-12-02 13:08:59 -06:00
U Cirello
6ce1de476a fix(run): allow messages to start with dash (-) (#4904) 2025-12-02 12:52:05 -06:00
Aiden Cline
d9b0848a61 tweak: hide [REDACTED] chunks 2025-12-02 12:29:20 -06:00
Adam
46dd3b8166 chore: update landing page stats 2025-12-02 11:59:37 -06:00
Adam
eca07be072 chore: update landing page stats 2025-12-02 11:52:53 -06:00
GitHub Action
165d57b88e chore: format code 2025-12-02 17:07:27 +00:00
David Hill
28c44f7e5a Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-12-02 17:06:54 +00:00
David Hill
39d5bdff4b fix: add docs button 2025-12-02 17:06:37 +00:00
GitHub Action
b9f8480b2f chore: format code 2025-12-02 17:02:39 +00:00
David Hill
58b30d678a Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-12-02 17:00:45 +00:00
David Hill
408cdaf5e0 fix: website hero copy 2025-12-02 17:00:40 +00:00
GitHub Action
cae23cde09 chore: format code 2025-12-02 16:45:56 +00:00
Dalton Alexandre
702fb2562c fix: handle ANSI color indexes in theme resolution (#4842) 2025-12-02 10:45:22 -06:00
opencode
785d0b60b6 release: v1.0.127 2025-12-02 16:05:59 +00:00
Adam
67ab9dc4d0 fix: share page ssr 2025-12-02 07:08:25 -06:00
Github Action
77494cb7df Update Nix flake.lock and hashes 2025-12-02 12:52:28 +00:00
GitHub Action
08f8856d6c chore: format code 2025-12-02 12:51:37 +00:00
Adam
79a4c1544d fix: type error 2025-12-02 06:51:05 -06:00
Adam
c0a35141e6 feat: better code and diff rendering performance 2025-12-02 06:50:21 -06:00
GitHub Action
221bb64aeb ignore: update download stats 2025-12-02 2025-12-02 12:04:35 +00:00
David Hill
2555dba188 fix: update the install copy 2025-12-02 11:37:41 +00:00
Aiden Cline
6355ed6ae7 feat: add overridable review slash command (#4973) 2025-12-02 00:18:58 -06:00
Ariane Emory
1864e8c863 feat: toggle tool details visibility (resolves #4824) (#4882)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-12-01 19:38:44 -06:00
Adam
61d0d66dae fix: install orange 2025-12-01 19:21:55 -06:00
Aiden Cline
86522f1b3e fix: tui crash when no authed providers and default provider disabled (#4964) 2025-12-01 18:35:40 -06:00
Frank
dc32705bc9 zen: remove unnecessary transactions 2025-12-01 18:33:32 -05:00
Stephen Collings
1eaf5c31d3 fix(auth): Respect disabled/enabled providers config in auth login (#4940)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-12-01 17:01:10 -06:00
Aiden Cline
677b19e22e fix: add .quiet 2025-12-01 16:59:32 -06:00
opencode-agent[bot]
8e248ae045 fix: respect npm registry (#4958)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-12-01 16:58:39 -06:00
Adam
0acefd5c08 fix: safari icons 2025-12-01 16:27:12 -06:00
Aiden Cline
0331931f56 fix: sanitize more invalid schema cases for gemini models 2025-12-01 16:19:10 -06:00
Dax Raad
01e2c9cc21 core: fix share compaction reprocessing same events by making storage list boundaries exclusive 2025-12-01 16:58:59 -05:00
Dax Raad
4acb645f04 core: add debug logging to troubleshoot share compaction loading 2025-12-01 16:46:57 -05:00
Github Action
ef664039ac Update Nix flake.lock and hashes 2025-12-01 21:38:38 +00:00
Dax Raad
993422c6af core: prevent share tests from cleaning up storage used by other tests 2025-12-01 16:37:54 -05:00
Dax Raad
c950d59047 fix types 2025-12-01 16:36:56 -05:00
GitHub Action
cc726e0200 chore: format code 2025-12-01 21:35:51 +00:00
Dax Raad
3d99dc78db core: reduce latency when loading shared sessions through event compaction 2025-12-01 16:35:07 -05:00
Dax Raad
95c3a8b805 limit grep line length to 2000 2025-12-01 16:35:07 -05:00
Aiden Cline
f1bb5870ce fix: copilot responses bug w/ gpt 5 mini 2025-12-01 14:36:49 -06:00
GitHub Action
540407e193 chore: format code 2025-12-01 19:03:13 +00:00
Aiden Cline
027d43b5ea fix case where opencode wasn't retrying 2025-12-01 13:02:33 -06:00
opencode
729a6eda23 release: v1.0.126 2025-12-01 19:00:00 +00:00
blacksmith-sh[bot]
cbbd21e2e5 .github/workflows: Migrate workflows to Blacksmith runners (#4941)
Co-authored-by: blacksmith-sh[bot] <157653362+blacksmith-sh[bot]@users.noreply.github.com>
2025-12-01 09:43:33 -05:00
GitHub Action
e7d45ca617 chore: format code 2025-12-01 14:43:23 +00:00
Dax Raad
0ddfdb55d3 log fetch time 2025-12-01 09:35:08 -05:00
GitHub Action
fc439455a7 chore: format code 2025-12-01 14:23:36 +00:00
opencode
c0fc02769b release: v1.0.125 2025-12-01 14:23:35 +00:00
Dax Raad
068ac68496 docs: add rebase instructions to commit command 2025-12-01 09:14:54 -05:00
Dax Raad
7da6a22df2 core: close SSE stream when instance is disposed 2025-12-01 09:14:00 -05:00
Sebastian Herrlinger
e37aeb6e6a no conceal for write tool output 2025-12-01 15:12:47 +01:00
GitHub Action
eeb0d2b8e0 chore: format code 2025-12-01 13:27:29 +00:00
adamelmore
bf8c866bf7 chore: otf fonts 2025-12-01 07:20:53 -06:00
GitHub Action
75354b0002 ignore: update download stats 2025-12-01 2025-12-01 12:08:56 +00:00
opencode
4eb4d97d51 release: v1.0.124 2025-12-01 09:20:29 +00:00
Aiden Cline
b1b82977ec tweak: better err msgs 2025-12-01 01:33:32 -06:00
Aiden Cline
f6262460ff fix: drop absolute flag to resolve issues when using older git versions 2025-12-01 00:23:19 -06:00
GitHub Action
560a610384 chore: format code 2025-12-01 02:53:41 +00:00
Aiden Cline
0308b2ff98 bump anthropic plugin to fix header issue 2025-11-30 20:52:50 -06:00
opencode
5b92d49be7 release: v1.0.123 2025-12-01 01:07:50 +00:00
Github Action
0386d0ae09 Update Nix flake.lock and hashes 2025-12-01 01:00:23 +00:00
Sebastian Herrlinger
28bec57e1d bump opentui to v0.1.54, removing the cc flicker feature, fixing diffs and input event handling 2025-12-01 01:57:55 +01:00
Shantur Rathore
aaa31f02af tweak: compaction prompt (#4838)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-30 14:31:57 -06:00
Justin Vogt
ff609a52c1 docs: explore subagent (#4893) 2025-11-30 14:04:27 -06:00
GitHub Action
1e30793f0a ignore: update download stats 2025-11-30 2025-11-30 12:04:23 +00:00
Adam
5268eb479d feat(share): split diffs on wide screens 2025-11-30 05:29:07 -06:00
Aiden Cline
a4eba2e6e9 tweak: plan prompt 2025-11-30 01:03:35 -06:00
Aiden Cline
0f30115205 chore: cleanup 2025-11-30 00:32:43 -06:00
opencode-agent[bot]
ae500ea01d Added "Open docs" command to palette (#4915)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-29 23:49:45 -06:00
Justin Vogt
087479d459 docs: Move tip to correct tool (#4891) 2025-11-29 22:03:20 -06:00
Aiden Cline
6e2379a28c get codex working in copilot (#4914)
Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-11-29 21:47:29 -06:00
opencode
262fa184fd release: v1.0.122 2025-11-30 00:35:34 +00:00
Github Action
9a7e1c154d Update Nix flake.lock and hashes 2025-11-29 23:56:14 +00:00
Sebastian Herrlinger
5bf9193dfa bump opentui to v0.1.53, fixing an event listener leak in the line number renderable (perf) 2025-11-30 00:52:32 +01:00
Sebastian Herrlinger
180fb3f39d tweak spinner to be bg independent 2025-11-30 00:50:30 +01:00
GitHub Action
7e6b7314f4 chore: format code 2025-11-29 21:41:00 +00:00
Dax Raad
a262508fb8 core: clarify general agent can execute multiple parallel tasks 2025-11-29 16:40:15 -05:00
Dax Raad
80ff24b65a ci: allow snapshot builds from any branch starting with snapshot- prefix 2025-11-29 21:30:38 +00:00
opencode
012aa67e42 release: v1.0.121 2025-11-29 21:30:38 +00:00
Github Action
0a1f12a583 Update Nix flake.lock and hashes 2025-11-29 21:20:24 +00:00
Sebastian Herrlinger
f17dc812d0 upgrade opentui to v0.1.52, fixing #4906 - key repeat handling 2025-11-29 22:18:08 +01:00
kavin
1854d85ccc fix(tui): add missing fg color to permission keybind hints (#4899)
Co-authored-by: Github Action <action@github.com>
2025-11-29 14:22:20 -06:00
Adam
2c4d1fb8b4 chore: cleanup duplicate markup 2025-11-29 06:18:51 -06:00
GitHub Action
d8fa7cf65d ignore: update download stats 2025-11-29 2025-11-29 12:04:12 +00:00
Dorian Karter
7d8d360138 fix: minor ui bug for transparent backgrounds (#4886) 2025-11-28 23:58:44 -06:00
Dax Raad
d80880350d core: improve explore agent description to clarify tool availability 2025-11-28 21:47:45 -05:00
GitHub Action
b693ed0dbd chore: format code 2025-11-29 02:44:40 +00:00
Dax Raad
83f961a7c2 Merge remote-tracking branch 'origin/dev' into dev 2025-11-28 21:44:02 -05:00
Dax Raad
a093917db1 core: update generated types to include explore agent configuration 2025-11-28 21:43:56 -05:00
opencode
52716db649 release: v1.0.120 2025-11-29 02:34:23 +00:00
Dax Raad
9ca4b464ea tui: improve task display in session view to show tool names and completion status 2025-11-28 21:19:15 -05:00
Dax Raad
204a31b6bb Merge remote-tracking branch 'origin/dev' into dev 2025-11-28 21:13:13 -05:00
Dax Raad
813d287a09 core: add explore agent for fast codebase navigation and improve task UI display 2025-11-28 21:13:07 -05:00
Adam
4dd9f33eba fix: diffs double rendering when CSR'd 2025-11-28 20:08:50 -06:00
Adam
5953378a12 fix: theme-color value 2025-11-28 19:57:01 -06:00
Github Action
b419eed295 Update Nix flake.lock and hashes 2025-11-29 01:55:02 +00:00
Sebastian Herrlinger
52deb7f352 opentui diffs 2025-11-29 02:52:17 +01:00
Dax Raad
a4f3aecbaa ignore 2025-11-28 20:29:58 -05:00
GitHub Action
49ff6a852a chore: format code 2025-11-28 22:43:33 +00:00
Justin Vogt
7f537d2e98 docs: Add tip to tools about subagents re todos (#4875) 2025-11-28 15:49:24 -06:00
Aiden Cline
753443b16f ci: add community contributors to the changelog 2025-11-28 15:44:21 -06:00
Ariane Emory
33c63be980 feat: persist thinking blocks display to KV and indicate its current display state in the command_list (resolves #4582) (#4810)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-28 15:01:05 -06:00
Aiden Cline
b6efca42b4 ci: use haiku 2025-11-28 14:41:32 -06:00
Github Action
fa6eadc39a Update Nix flake.lock and hashes 2025-11-28 20:32:46 +00:00
Aiden Cline
8789acefa6 bump openrouter & google ai sdk packages 2025-11-28 14:30:22 -06:00
Aiden Cline
0e280017e6 Revert "fix: title gen when first msg(s) are shell invocations (#4874)"
This reverts commit 17e8322c29.
2025-11-28 12:18:02 -06:00
Aiden Cline
17e8322c29 fix: title gen when first msg(s) are shell invocations (#4874)
Co-authored-by: GitHub Action <action@github.com>
2025-11-28 11:55:22 -06:00
Sergio Garcia
96eda740cd docs: formatter: false and lsp: false (#4833)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
2025-11-28 11:22:48 -06:00
jaov
fa84612357 tweak: gemini retry message to not be explicitly about gemini 3 (#4864)
Co-authored-by: jesuso <j.ochoa@norteconecta.net>
2025-11-28 11:14:53 -06:00
Dax Raad
cf1f63eda3 ci stuff 2025-11-28 10:59:52 -05:00
Dax Raad
9704f5ce89 add otui-diffs 2025-11-28 10:59:07 -05:00
GitHub Action
0eaec2af82 ignore: update download stats 2025-11-28 2025-11-28 12:04:42 +00:00
Adam
398d35dc97 fix: theme-color value 2025-11-28 05:48:07 -06:00
Adam
5efeaae093 fix: desktop and share layouts 2025-11-28 05:35:35 -06:00
Adam
cb2dd34a5e fix: unified diff as default 2025-11-28 05:35:35 -06:00
Christoph
7112a706b8 core: add built-in Dart LSP server and formatter (#4841) 2025-11-28 00:33:45 -06:00
Github Action
025a47d01f Update Nix flake.lock and hashes 2025-11-28 06:27:49 +00:00
DS
13f89fdb8f fix: filter empty messages in toModelMessage (#4811) 2025-11-28 00:26:48 -06:00
Aiden Cline
cc78d50ef6 bump anthropic package 2025-11-28 00:25:16 -06:00
Adam
a8985b1849 fix(desktop): layout 2025-11-27 20:15:49 -06:00
Adam
6a1552f65c fix: unwrap solid store part 2025-11-27 20:15:49 -06:00
Dax Raad
776091cc23 ci: add bun version check to pre-push hook to ensure version consistency 2025-11-27 15:50:23 -05:00
Dax Raad
f385524f48 fix lock 2025-11-27 15:48:16 -05:00
Dax Raad
350982e636 tui: simplify model dialog ordering logic to reduce complexity 2025-11-27 14:38:51 -05:00
Dax Raad
5854455815 tui: improve provider dialog text clarity for better user guidance 2025-11-27 14:09:53 -05:00
Dax Raad
9ecaf618db tui: fix provider sorting to prioritize recommended options 2025-11-27 13:54:42 -05:00
Dax Raad
95b667d21e tui: remove cancel keybind hint from prompt dialog to simplify UI 2025-11-27 13:48:34 -05:00
Dax Raad
a0b689c140 tui: hide favorite keybind in model dialog when disconnected to prevent errors 2025-11-27 13:42:36 -05:00
GitHub Action
ea52ed41be chore: format code 2025-11-27 17:15:41 +00:00
Jay V
5a50d54fda ignore: lock 2025-11-27 12:14:50 -05:00
Jay V
35d118b0c4 ignore: add reply-to support for enterprise form emails 2025-11-27 12:12:44 -05:00
Albert O'Shea
ea7c213f5d nix: fix workflow failing on PRs (#4820)
Co-authored-by: Github Action <action@github.com>
2025-11-27 10:05:51 -06:00
Frank
70dd6dd394 doc: slashing kimi k2 thinking price 2025-11-27 09:58:57 -05:00
GitHub Action
049510afbd ignore: update download stats 2025-11-27 2025-11-27 12:04:30 +00:00
Adam
c120447fd0 fix: desktop layout and scroll gutters 2025-11-27 05:41:50 -06:00
Adam
feb1f36126 fix: session turn margins 2025-11-27 05:25:39 -06:00
GitHub Action
d6ef47bb2d chore: format code 2025-11-27 11:06:46 +00:00
Adam
50fd416d49 fix: simpler sanitize 2025-11-27 05:05:55 -06:00
opencode
aef6904247 release: v1.0.119 2025-11-27 03:15:40 +00:00
Dax Raad
0bf40faf95 core: prevent codesearch and websearch tools when webfetch permission is denied 2025-11-26 22:08:50 -05:00
GitHub Action
c90987c4b0 chore: format code 2025-11-27 03:08:33 +00:00
Dax Raad
0e08655407 core: prevent external diff tools from interfering with snapshot generation 2025-11-26 22:07:51 -05:00
opencode
427887db9c release: v1.0.118 2025-11-27 02:43:07 +00:00
Dax Raad
a718622498 tui: prevent footer from shrinking when terminal is resized 2025-11-26 21:35:56 -05:00
Github Action
4e83107d79 Update Nix flake.lock and hashes 2025-11-27 01:33:35 +00:00
GitHub Action
04b6e72820 chore: format code 2025-11-27 01:32:04 +00:00
Dax Raad
501a2539c7 revert ts lsp to monorepo root 2025-11-26 20:31:26 -05:00
opencode
6a9856d480 release: v1.0.117 2025-11-27 01:29:00 +00:00
Dax Raad
2c8d42d997 roll back vtsls 2025-11-26 20:18:40 -05:00
Dax Raad
9c237f0bfb temporarily restrict codesearch and websearch to opencode zen users. need to figure out how to opt out for enterprise users who do not want this 2025-11-26 20:13:20 -05:00
Dax
63bfe76720 tui design refinement (#4809) 2025-11-26 20:11:39 -05:00
Aiden Cline
99d7ff47c4 enable parcel file watcher, expand parcel ignore patterns, replace fs watcher for git branches with parcel (#4805) 2025-11-26 17:33:43 -06:00
Aiden Cline
3ff0eb3065 Revert "fix: disable virtual extmarks for file/agent mentions (#4731)"
This reverts commit 673dbeee09.
2025-11-26 14:55:39 -06:00
GitHub Action
4d2b265dc4 chore: format code 2025-11-26 19:10:51 +00:00
rosmur
1854245bd3 docs: add llama.cpp provider for local LLM inference (#4769)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-26 13:10:15 -06:00
Aiden Cline
4d07034930 fix: svg paste bug 2025-11-26 12:38:48 -06:00
Dax Raad
98031173b6 lil branch refactor 2025-11-26 12:34:48 -05:00
GitHub Action
e8e474597c chore: format code 2025-11-26 17:26:46 +00:00
Tommy D. Rossi
382758790c fix(tui): dedupe file references in prompt (#4775) 2025-11-26 11:26:05 -06:00
opencode
c33920f59d release: v1.0.115 2025-11-26 16:57:35 +00:00
Jensen
33f004d4b6 fix(tui): show bootstrap errors instead of {} to trace (#4779)
Co-authored-by: Github Action <action@github.com>
2025-11-26 10:49:55 -06:00
Yug Agarwal
8963b536ee docs: IO.NET Provider (#4762) 2025-11-26 10:44:05 -06:00
GitHub Action
51455e2a1e ignore: update download stats 2025-11-26 2025-11-26 12:04:44 +00:00
Adam
30d6a26e3e fix: useData 2025-11-26 06:03:13 -06:00
Adam
cd4fabd11b fix: scroll gutter padding 2025-11-26 05:58:30 -06:00
Github Action
9a8b8f26ac Update Nix flake.lock and hashes 2025-11-26 11:31:37 +00:00
Adam
2f73b16b57 deps: update pierre diffs 2025-11-26 05:29:31 -06:00
opencode-agent[bot]
df9952c291 Renamed vcs.changed to vcs.branch.updated (#4771)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-26 01:17:59 -06:00
Dmitry Halushka
ee946d8128 fix: transform MCP tool schemas for Google/Gemini compatibility (#4538)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: Github Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-26 00:58:20 -06:00
Aiden Cline
ec8f2e078e Remove keybinds from favorites feature, keep functionality 2025-11-26 00:45:33 -06:00
shuv
335f46122b Add favorites to model selector (#23) (#4343)
Co-authored-by: Github Action <action@github.com>
2025-11-26 00:41:41 -06:00
Meysam Najafi Fard
73eae191e9 fix: handle remote image URLs in paste handler (#4691)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-26 00:34:22 -06:00
Aiden Cline
14e823e938 ignore: fix type issue 2025-11-26 00:14:04 -06:00
Aiden Cline
2fbd462e6e Reapply "feat(github): add ability to react to PR Review Comments in Workflow (#4705)"
This reverts commit e1cc98d448.
2025-11-25 23:51:46 -06:00
Aiden Cline
e1cc98d448 Revert "feat(github): add ability to react to PR Review Comments in Workflow (#4705)"
This reverts commit 0ce64962d4.
2025-11-25 23:51:23 -06:00
U Cirello
0ce64962d4 feat(github): add ability to react to PR Review Comments in Workflow (#4705)
Co-authored-by: GitHub Action <action@github.com>
2025-11-25 23:45:19 -06:00
george larson
338229193f docs: add Venice.ai provider (#4748)
Co-authored-by: George Larson <georgeglarson@users.noreply.github.com>
2025-11-25 23:40:52 -06:00
Ariane Emory
57644a4be8 feat: add a diff_style option to allow disabling columnar diffs (resolve #4677) (#4756)
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-25 23:34:58 -06:00
Frank
da2099137a zen: trial 2025-11-25 23:44:57 -05:00
Aiden Cline
09bc8d9ca4 show current git branch in tui (#4765)
Co-authored-by: GitHub Action <action@github.com>
2025-11-25 21:39:20 -06:00
Dax Raad
d95f724303 enable exa code/websearch 2025-11-25 22:06:26 -05:00
Frank
c413c3ed8f wip: zen 2025-11-25 22:01:34 -05:00
Adam
5f56be0ad4 fix: pierre separators 2025-11-25 20:39:20 -06:00
Adam
ef441d5cff chore: cleanup pierre stuff 2025-11-25 20:39:20 -06:00
GitHub Action
16a188c524 chore: format code 2025-11-26 02:33:36 +00:00
Dax Raad
50c40a8d99 tui: fix event subscription cleanup in SDK context 2025-11-25 21:32:56 -05:00
opencode
4114c8715c release: v1.0.114 2025-11-26 00:32:22 +00:00
GitHub Action
ced5fdbe70 chore: format code 2025-11-26 00:24:10 +00:00
Dax Raad
b16aa81e0d switch to vtsls for typescript lsp 2025-11-25 19:23:23 -05:00
Aiden Cline
b44971668c fix: global prefix handling w/ aws bedrock (#4757) 2025-11-26 00:21:59 +00:00
opencode
0ff4c284e2 release: v1.0.113 2025-11-26 00:21:59 +00:00
Dax Raad
e8db95be16 switch typescript lsp to be one per package to ensure it loads when typescript is not installed at root 2025-11-25 19:14:07 -05:00
Shantur Rathore
69c2dd53ad config: add setCacheKey in provider options (#4738)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-25 17:53:56 -06:00
Frank
14a910bd64 wip: zen 2025-11-25 18:04:25 -05:00
GitHub Action
52f97ffdc9 chore: format code 2025-11-25 22:59:55 +00:00
Frank
a1e87f6cd9 wip: zen 2025-11-25 17:58:59 -05:00
Frank
c2fc41dcd5 wip: zen 2025-11-25 17:57:24 -05:00
Frank
b62c7943e7 zen: trial 2025-11-25 17:57:24 -05:00
Tommy D. Rossi
64caeeb12d fix(tui): abort in-progress generation on undo (#4744) 2025-11-25 16:35:34 -06:00
Adam
e8ac4a1e99 fix: build error 2025-11-25 16:27:53 -06:00
Adam
19c8654195 fix: missing deps 2025-11-25 16:27:26 -06:00
Haris Gušić
00d7aed797 fix: prompt submit error with opencode -c (#4496)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-25 16:27:06 -06:00
Adam
4477132448 fix: sanitize absolute paths 2025-11-25 16:02:31 -06:00
Aiden Cline
eaeea45ace ci: change changelog model 2025-11-25 15:36:26 -06:00
Aiden Cline
e404bf33b1 update install script to handle musl & avx 2025-11-25 15:35:10 -06:00
Aiden Cline
79a7edea5e ci: update changelog prompt 2025-11-25 15:34:49 -06:00
Jaga Santagostino
2b05fe2859 docs: improve notes on mobile (#4747) 2025-11-25 15:27:28 -06:00
GitHub Action
f8996f0a90 chore: format code 2025-11-25 21:10:31 +00:00
Dax Raad
eb04cdac41 better overloaded message 2025-11-25 21:10:31 +00:00
opencode
125938c7a1 release: v1.0.112 2025-11-25 21:10:30 +00:00
opencode
ec1260d8aa release: v1.0.111 2025-11-25 20:54:40 +00:00
Dax Raad
9eabbe2e76 retry anthropic overloaded errors 2025-11-25 15:47:34 -05:00
Adam
5f35c579e2 fix: accordion styles 2025-11-25 14:46:22 -06:00
Adam
99a23bdc8f fix: css code splitting off for desktop 2025-11-25 14:33:49 -06:00
Aiden Cline
d914a08896 tweak stats command to show avg & median # of tokens per session 2025-11-25 14:14:06 -06:00
Jaga Santagostino
ceccc30cb8 docs: reduce mobile padding (#4745) 2025-11-25 14:04:55 -06:00
Youssef Achy
3366a71155 Theme selector UX (current theme indicator and easier selection) (#4623)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-25 13:53:01 -06:00
Adam
cd67804412 fix: scroll gutter 2025-11-25 13:49:46 -06:00
Aiden Cline
4a95db6013 fix: add missing compacted event 2025-11-25 13:47:10 -06:00
Adam
8bf552ae25 fix: markdown inline code style 2025-11-25 13:11:21 -06:00
Adam
ccd0c2382f fix(share): style issues 2025-11-25 12:53:43 -06:00
Adam
d74663bf53 fix(share): don't highlight words unless split 2025-11-25 12:21:39 -06:00
Aiden Cline
020ee56f25 fix: dont auto continue if compaction was manual 2025-11-25 12:11:09 -06:00
Adam
87b295bc3d fix(share): metadata and popover close delay 2025-11-25 12:09:22 -06:00
Github Action
b9b1e92788 Update Nix flake.lock and hashes 2025-11-25 17:45:45 +00:00
Dax Raad
4000705701 core(enterprise): use aws4fetch for smaller bundle size on edge runtimes 2025-11-25 12:43:36 -05:00
Tommy D. Rossi
673dbeee09 fix: disable virtual extmarks for file/agent mentions (#4731) 2025-11-25 11:37:46 -06:00
Ariane Emory
5288041782 tweak: alphabetical (mostly) opencode models output (#4725)
Co-authored-by: Dax Raad <d@ironbay.co>
2025-11-25 11:37:05 -06:00
Ariane Emory
4273fa9ccf fix: merge plugin selections (resolves #4565) (#4724)
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-25 11:34:21 -06:00
Aiden Cline
01bcb9dff9 ci: setup bun 2025-11-25 11:27:29 -06:00
Github Action
101f86ad1f Update Nix flake.lock and hashes 2025-11-25 16:56:01 +00:00
GitHub Action
2575dc2db0 chore: format code 2025-11-25 16:46:00 +00:00
Adam
b4e6f128d7 fix: favicons across all web properties 2025-11-25 10:45:18 -06:00
Albert O'Shea
7d5e6718dc nix: set dontFixup = true (#4735) 2025-11-25 10:16:53 -06:00
Github Action
072aa7569c Update Nix flake.lock and hashes 2025-11-25 13:50:22 +00:00
GitHub Action
62871283e2 chore: format code 2025-11-25 13:49:03 +00:00
Adam
0f1dd24f97 fix(enterprise): custom element defs 2025-11-25 07:48:18 -06:00
Adam
995f551e80 fix(enterprise): custom element defs 2025-11-25 07:47:25 -06:00
Adam
15facd8cfd feat(share): SSR'd diffs 2025-11-25 07:40:16 -06:00
GitHub Action
57bd47a446 ignore: update download stats 2025-11-25 2025-11-25 12:05:06 +00:00
Aiden Cline
0568c943ab better scroll speed default for windows 2025-11-25 01:16:21 -06:00
Shantur Rathore
b1aaa8570e prompt_async: Allows to receive prompt and return immediately, start … (#4664)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-24 23:52:57 -06:00
Aiden Cline
3b2aa7e91d Revert "Support basic auth in opencode sdk (#4697)"
This reverts commit b9253d0b3b.
2025-11-24 23:12:00 -06:00
Aiden Cline
997aacf7f0 ci: adjust nix hash 2025-11-24 22:50:32 -06:00
Dax Raad
3183978c6b fixed suspense in enterprise 2025-11-24 23:33:47 -05:00
Frank
6a0b20456f zen: remove official support for unified endpoint 2025-11-24 23:33:23 -05:00
Frank
8841112b07 zen: add zai logo 2025-11-24 23:33:23 -05:00
Aiden Cline
16dbac6026 Revert "config: add setCacheKey in provider options (#4654)"
This reverts commit 9b6d03c497.
2025-11-24 22:30:56 -06:00
Shantur Rathore
9b6d03c497 config: add setCacheKey in provider options (#4654)
Co-authored-by: GitHub Action <action@github.com>
2025-11-24 22:20:52 -06:00
Aiden Cline
d3ea044619 ignore: comment out thingy 2025-11-24 22:15:00 -06:00
Frank
364355c8e1 zen: graduate kimi k2 thinking 2025-11-24 23:14:46 -05:00
Frank
88c4e95428 zen: sticky session 2025-11-24 23:14:46 -05:00
Dax Raad
9403f6ced5 log data 2025-11-24 23:13:28 -05:00
GitHub Action
56fe84e516 chore: format code 2025-11-25 03:59:28 +00:00
Dax Raad
69d1381ba3 core: refactor share system to separate session IDs from share IDs
- Generate shorter share IDs from session IDs for better URL structure
- Update API routes to use shareID parameter instead of sessionID
- Improve sync mechanism with better data queuing and deduplication
- Maintain backward compatibility while improving security and organization
2025-11-24 22:58:47 -05:00
Dax Raad
ccec8c4792 tui: align session panel content with consistent left padding 2025-11-25 03:08:12 +00:00
opencode
83c47e0ed7 release: v1.0.110 2025-11-25 03:08:12 +00:00
Dax Raad
6d630901b6 tui: use standard middle dot separator for better terminal compatibility 2025-11-24 22:00:44 -05:00
Adam
320622fc27 fix(tui): spacing 2025-11-24 20:44:30 -06:00
Dax Raad
fb8ef1f27b tui: prevent re-fetching already synced sessions when switching sessions 2025-11-24 21:43:11 -05:00
Adam
333948711d fix(desktop): content animations 2025-11-24 20:35:51 -06:00
Adam
001b4be0ae fix(desktop): message summaries 2025-11-24 19:56:12 -06:00
Github Action
427c62d052 Update Nix flake.lock and hashes 2025-11-25 00:03:08 +00:00
Sebastian Herrlinger
99097d418b bump opentui to v0.1.50
- fix another segfault
- fix weird tmux window/pane title
- fix selection in textarea (use shift+arrow keys)
2025-11-25 01:00:48 +01:00
Adam
75654afeaa fix(share): responsiveness 2025-11-24 17:59:37 -06:00
GitHub Action
f10d18956a chore: format code 2025-11-24 23:06:21 +00:00
Andrew Joslin
b9253d0b3b Support basic auth in opencode sdk (#4697) 2025-11-24 17:05:35 -06:00
opencode
2458e7597b release: v1.0.109 2025-11-24 22:30:42 +00:00
Aiden Cline
23a721f0a2 remove hardcoded openrouter provider 2025-11-24 16:11:12 -06:00
Frank
9bd6be5c6d zen: byok for gemini 2025-11-24 17:09:54 -05:00
Adam Hosker
dd6113c9d1 Add --refresh flag to models command (#4707) 2025-11-24 16:06:51 -06:00
Adam
d39bcd9c55 fix(desktop): layout 2025-11-24 15:57:48 -06:00
Frank
823d7da4c1 zen: display reasoning tokens 2025-11-24 16:54:54 -05:00
Frank
7fff191c57 wip: zen 2025-11-24 16:54:54 -05:00
Aiden Cline
9e44085a69 adjust bundled provider logic, fix tree shaking stuff (#4708) 2025-11-24 15:48:54 -06:00
Adam
5230b91b25 fix(console): remove extra favicon 2025-11-24 15:48:11 -06:00
GitHub Action
493b3d72e4 chore: format code 2025-11-24 21:17:40 +00:00
Adam
337590c450 fix(console): favicon issues 2025-11-24 15:10:40 -06:00
Adam
8e1c7cfe89 wip(share): enterprise favicon 2025-11-24 15:10:40 -06:00
Adam
c60cb6c329 wip(share): more styling 2025-11-24 15:10:40 -06:00
Adam
acf1dd8500 wip(share): more styling 2025-11-24 15:10:40 -06:00
Adam
3fb57044d1 wip(share): more styling 2025-11-24 15:10:39 -06:00
Frank
46a76a778a zen: add opus 4.5 2025-11-24 15:39:38 -05:00
Aiden Cline
a9a2c23736 add autoupdate: notify 2025-11-24 14:32:38 -06:00
Aiden Cline
ccde319937 ci: nix hash 2025-11-24 14:26:55 -06:00
Frank
0ed7fac5fb wip: zen 2025-11-24 15:24:44 -05:00
GitHub Action
80b9cd1292 chore: format code 2025-11-24 19:53:00 +00:00
Sebastian Herrlinger
b6c1df41fb textarea highlight cursor color 2025-11-24 20:51:07 +01:00
opencode
125af820d0 release: v1.0.108 2025-11-24 19:16:14 +00:00
GitHub Action
8167e90801 chore: format code 2025-11-24 18:40:01 +00:00
Sebastian Herrlinger
82ebf66cba non-corpo loading spinner 2025-11-24 19:39:09 +01:00
Frankie Seabrook
883ed4d424 docs: add Ollama Cloud provider setup to providers.mdx (#4693) 2025-11-24 10:51:16 -06:00
GitHub Action
e6bf1754c3 ignore: update download stats 2025-11-24 2025-11-24 12:04:34 +00:00
Carli Samuele
bcb494d5d1 TUI: fix: add null check for user.time in duration calculation (#4679) 2025-11-24 02:06:09 -06:00
Ariane Emory
75c0c0a098 tweak: display MCPs in alphabetic order in the sidebar. (#4680)
Co-authored-by: Github Action <action@github.com>
2025-11-24 02:02:04 -06:00
GitHub Action
840d2694b4 chore: format code 2025-11-24 07:51:59 +00:00
Aiden Cline
abdc7b276a fix: persist light vs dark mode 2025-11-24 01:51:13 -06:00
Aiden Cline
d4f6deb9ef tweak: modified files sidebar 2025-11-24 01:51:13 -06:00
opencode
502e85b903 release: v1.0.107 2025-11-24 07:06:41 +00:00
Aiden Cline
ac1e2bfd49 bump copilot plugin, give better error message for copilot (#4678) 2025-11-24 00:40:15 -06:00
Aiden Cline
b9b071c744 fix: fatal: undefined is not an object (evaluating 'color.buffer') 2025-11-23 23:56:15 -06:00
GitHub Action
83186b6fed chore: format code 2025-11-24 04:55:13 +00:00
Albert O'Shea
a3a239967f nix: bundle js dist with bun and patch tree-sitter wasm paths (#4644)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: Github Action <action@github.com>
2025-11-23 22:54:29 -06:00
Huang Qi
b4fd4bb257 fix: add explicit fallback model and prevent direct opencode provider calls (#4653)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-23 22:51:15 -06:00
GitHub Action
eb009d5959 chore: format code 2025-11-23 20:59:37 +00:00
Frank
4a81bd0f50 wip: zen 2025-11-23 15:58:55 -05:00
Frank
bbc9142fc5 wip: zen 2025-11-23 15:21:47 -05:00
Aiden Cline
7413c2715c tweak: slight improvements to title gen 2025-11-23 14:04:39 -06:00
Dax Raad
7579c3bb15 ci: remove log 2025-11-23 15:00:29 -05:00
Dax Raad
24683058fd ci: ignore 2025-11-23 14:56:24 -05:00
Dax Raad
bf81e3108c ci: ignore 2025-11-23 14:56:24 -05:00
Dax Raad
5ade90416e ci: ignore 2025-11-23 14:44:05 -05:00
GitHub Action
8f2a8086c0 chore: format code 2025-11-23 19:37:19 +00:00
Dax Raad
38b70f7877 ci: secret 2025-11-23 14:36:36 -05:00
Dax Raad
5e112a17a5 token 2025-11-23 19:35:39 +00:00
Dax Raad
59a3e7e3cc ci: ignore 2025-11-23 19:35:39 +00:00
Github Action
2c93f065cb Update Nix flake.lock and hashes 2025-11-23 19:35:39 +00:00
opencode
488d33c1ed release: v1.0.106 2025-11-23 19:35:38 +00:00
Dax Raad
de4660ac12 ci: ignore 2025-11-23 14:28:10 -05:00
Aiden Cline
27ae341684 fix bash tool wsl 2025-11-23 12:29:15 -06:00
Github Action
25b3846694 Update Nix flake.lock and hashes 2025-11-23 17:57:34 +00:00
Dax Raad
8e2f9f6544 ci: stuff 2025-11-23 12:55:33 -05:00
Github Action
76b5870f89 Update Nix flake.lock and hashes 2025-11-23 17:45:24 +00:00
Dax Raad
604891e793 ci: stuff 2025-11-23 12:43:23 -05:00
Dax Raad
5814df7eaa sync 2025-11-23 12:43:23 -05:00
Aiden Cline
2509d03f42 tweak: fix bool 2025-11-23 11:43:09 -06:00
Github Action
a256df9823 Update Nix flake.lock and hashes 2025-11-23 17:09:33 +00:00
Dax Raad
af96ec5a30 ignore: update @solidjs/start dependency and fix console redirect handling
Updates the @solidjs/start dependency to latest version and removes deprecated getResponseHeaders usage from auth callback. Also adds error handling for workspace ID lookup to prevent redirect failures.
2025-11-23 12:07:28 -05:00
GitHub Action
55df80b80e ignore: update download stats 2025-11-23 2025-11-23 12:04:01 +00:00
Ariane Emory
7d11986a0a feature: optional selectedListItemText element in themes and luminance-based fallback to solve 4369 (#4572)
Co-authored-by: knanao <nao.7ken@gmail.com>
Co-authored-by: knanao <k@knanao.com>
2025-11-23 01:51:07 -06:00
Aiden Cline
d75d90c53e ci: fix action 2025-11-23 01:36:45 -06:00
Tyler Limbach
35fead2eca fix: make tui session text respect theme fg (#4618) (#4620) 2025-11-23 01:34:31 -06:00
Github Action
9bb2efd3ef Update Nix flake.lock and hashes 2025-11-23 07:31:17 +00:00
Aiden Cline
30ffcaa667 tweak: start bundling in some ai-sdk packages (#4649) 2025-11-23 01:29:20 -06:00
terakael
ba11455786 fix: prevent permission shortcuts when ctrl/meta pressed (#4631)
Co-authored-by: terakael <terakael@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-22 23:58:10 -06:00
Dax Raad
d69ba27f84 fix suspense 2025-11-23 00:16:06 -05:00
Dax Raad
448b72d046 fix logout 2025-11-23 00:12:58 -05:00
Dax Raad
d96d89bcb8 fix logout 2025-11-22 23:59:50 -05:00
Dax Raad
7a013d4f40 fixed 2025-11-22 23:56:37 -05:00
GitHub Action
e4597df3b9 chore: format code 2025-11-23 04:54:26 +00:00
Dax Raad
2b014fcd75 fix auth 2025-11-22 23:53:41 -05:00
Github Action
c2bf6975f8 Update Nix flake.lock and hashes 2025-11-23 00:44:43 +00:00
Sebastian Herrlinger
733e1f79ac bump opentui to v0.1.49
- fix stdin handling for suspend/resume
- fix textarea cursor movement segfault for wcdwidth (alacritty/tmux)
2025-11-23 01:42:33 +01:00
GitHub Action
2a6cbfd5fd chore: format code 2025-11-23 00:20:07 +00:00
Adam
6173b69a8b wip(share): more styling 2025-11-22 18:19:02 -06:00
opencode
fc72cfe784 release: v1.0.105 2025-11-22 22:39:18 +00:00
Dax Raad
768c81cdfd core: prevent concurrent bun package installs that could cause corruption or conflicts 2025-11-22 17:32:53 -05:00
Dax Raad
bcea8ed593 tui: fix message completion timing and duration display in session view 2025-11-22 17:28:50 -05:00
GitHub Action
f93bb1dd21 chore: format code 2025-11-22 22:27:23 +00:00
Ravi Kumar
b92e8510f9 fix: auto upgrade toast message (#4625)
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: opencode <opencode@sst.dev>
2025-11-22 16:26:46 -06:00
opencode
1b692ec7eb release: v1.0.104 2025-11-22 20:03:20 +00:00
Dax Raad
4c97e2e8bb reset cache 2025-11-22 14:56:35 -05:00
Dax Raad
b652198979 load desktop app 2025-11-22 14:40:11 -05:00
Dax Raad
31c4a1d853 docs: add Docker installation option for OpenCode 2025-11-22 14:13:04 -05:00
Goni Zahavy
6afdb5c0e5 tui: added ctrl-z terminal suspension support (#3983) 2025-11-22 12:48:23 -06:00
shuv
bdcf864678 proper fix for image attachments (#4562)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-22 12:47:57 -06:00
opencode
0dd5039668 release: v1.0.103 2025-11-22 18:21:49 +00:00
Dax Raad
a0831eade1 tui: remove bullet prefix from timestamps in session view for cleaner display 2025-11-22 13:11:08 -05:00
GitHub Action
f1dc9818b6 chore: format code 2025-11-22 18:04:34 +00:00
Dax Raad
b52b7c6ded more flickering fixes 2025-11-22 13:03:44 -05:00
Dax Raad
e03a41144a tui: keep assistant footer from crashing after compaction 2025-11-22 18:00:54 +00:00
opencode
37bb07e7a3 release: v1.0.100 2025-11-22 18:00:54 +00:00
Dax Raad
78a6325b64 improve model footer 2025-11-22 12:54:02 -05:00
GitHub Action
c96923d2c9 chore: format code 2025-11-22 17:50:32 +00:00
Valerio Di Maggio
59742fbfee Showed end time for agent loop and changed message time to show date if not current day (#4503)
Co-authored-by: GitHub Action <action@github.com>
2025-11-22 11:49:50 -06:00
Dax Raad
2938a25ec5 sync 2025-11-22 16:43:47 +00:00
opencode
d163eb3888 release: v1.0.99 2025-11-22 16:43:46 +00:00
Dax Raad
75c29d4d1c summary optimizaitons 2025-11-22 11:32:49 -05:00
Dax Raad
e103fb1f93 ci: add Node.js setup to deploy workflow for consistent runtime environment 2025-11-22 10:47:18 -05:00
Dax Raad
bd79ff87cc fix missing vite 2025-11-22 10:45:06 -05:00
Dax Raad
ac21ec2f46 upgrade bun lock version 2025-11-22 10:42:09 -05:00
Github Action
5bcf017c10 Update Nix flake.lock and hashes 2025-11-22 15:41:29 +00:00
Brendan Allan
85d99198b5 Use devinxi-ed Solid Start (#4635)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Dax Raad <d@ironbay.co>
2025-11-22 10:39:25 -05:00
GitHub Action
7f183f7404 ignore: update download stats 2025-11-22 2025-11-22 12:04:02 +00:00
opencode
85284df725 release: v1.0.98 2025-11-22 06:00:23 +00:00
Dax Raad
87054ee983 fix flickering/layout shift during work 2025-11-22 00:49:35 -05:00
GitHub Action
81245c2548 chore: format code 2025-11-22 05:15:55 +00:00
Dax Raad
6f82b321d8 tauri 2025-11-22 00:15:01 -05:00
opencode
f4593c6653 release: v1.0.97 2025-11-22 05:02:16 +00:00
Dax Raad
15902cf54d core: add missing system libraries to docker image so the agent starts successfully 2025-11-21 23:52:01 -05:00
GitHub Action
d1102c33ac chore: format code 2025-11-22 04:48:52 +00:00
Dax Raad
aabbd3383c fix dockerfile 2025-11-21 23:48:09 -05:00
opencode
afb55cb7d4 release: v1.0.95 2025-11-22 04:27:20 +00:00
Dax Raad
ade794a937 ci: ignore 2025-11-21 23:08:35 -05:00
Dax Raad
34271a82ff release: v1.0.94 2025-11-21 23:06:37 -05:00
Dax Raad
b20a31098a sync 2025-11-21 22:58:20 -05:00
Dax Raad
b5a039e5ae ci stuff 2025-11-21 22:53:58 -05:00
GitHub Action
986cc0a01c chore: format code 2025-11-22 03:31:29 +00:00
opencode
b20fd36c48 release: v1.0.92 2025-11-22 03:31:28 +00:00
Dax Raad
e4e6bf66e1 publish tar.gz for linux 2025-11-21 22:24:36 -05:00
opencode
3ae27273c6 release: v1.0.91 2025-11-22 02:19:56 +00:00
Dax Raad
eefb3c43dd fix arg parsing 2025-11-21 21:13:43 -05:00
Github Action
cc229e726e Update Nix flake.lock and hashes 2025-11-22 01:43:03 +00:00
Dax
49408c00e9 enterprise (#4617)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
2025-11-21 20:41:27 -05:00
opencode
76192fbced release: v1.0.90 2025-11-22 00:16:10 +00:00
GitHub Action
a1c76c79de chore: format code 2025-11-22 00:09:32 +00:00
Dax Raad
db9e2b1aac ci: disable automatic config loading during CLI builds to prevent configuration interference 2025-11-21 19:08:51 -05:00
opencode
45c4970d68 release: v1.0.89 2025-11-22 00:00:23 +00:00
Tommy D. Rossi
1d7a9309d6 feat: lower opacity for thinking summaries (#4610) 2025-11-21 17:35:47 -06:00
Dax Raad
f5ac98251e tui: split revert memo into smaller tracked computations to prevent unnecessary re-evaluations 2025-11-21 18:27:25 -05:00
GitHub Action
78239045ba chore: format code 2025-11-21 22:42:39 +00:00
Dax Raad
d8b60875c4 tui: batch SDK events to reduce render churn and improve responsiveness
Intelligently queue events and flush them in 16ms batches. Events processed within 16ms of the last flush are batched together to reduce the number of store updates and re-renders, preventing jank when receiving rapid consecutive events. Events after a 16ms gap are processed immediately to avoid adding latency.
2025-11-21 17:42:02 -05:00
opencode
48949a6e9d release: v1.0.88 2025-11-21 22:37:46 +00:00
GitHub Action
082a330ea3 chore: format code 2025-11-21 22:30:46 +00:00
Aiden Cline
adf7df0d5c tweak: bash tool behavior w/ /bin/zsh 2025-11-21 16:30:00 -06:00
opencode
a76ad48563 release: v1.0.87 2025-11-21 21:58:10 +00:00
Dax Raad
00f991162f if finish reason is unknown, continue 2025-11-21 16:51:32 -05:00
Frank
d6cdd24fad doc: update gpt pricing 2025-11-21 15:48:54 -05:00
GitHub Action
c9473756df chore: format code 2025-11-21 20:33:42 +00:00
Ivan Starkov
b5d0c56b4c fix: make bash tool respect $SHELL (#3494)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-21 14:33:04 -06:00
opencode
96a2f5268c release: v1.0.86 2025-11-21 20:32:47 +00:00
Aiden Cline
5083f9c9c2 bump bun to 1.3.3 2025-11-21 13:56:46 -06:00
Frank
e34df15ff5 update logic for local and dev providers 2025-11-21 13:31:33 -05:00
GitHub Action
26ec87803a chore: format code 2025-11-21 17:57:33 +00:00
Frank
037e8d4555 wip: zen 2025-11-21 12:50:51 -05:00
Adam
08a366c4dc feat(install): better install script visuals, custom progress bar and next steps (#4589) 2025-11-21 07:29:52 -06:00
GitHub Action
670e1523e0 ignore: update download stats 2025-11-21 2025-11-21 12:04:49 +00:00
Patrick Wolf
416f2964b5 fix: preserve agent context during compaction (#4556) 2025-11-21 02:13:10 -06:00
Ian Maurer
e018e16898 fix(cli): ensure clean exit on provider/model errors (#4223)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-21 02:01:19 -06:00
Aiden Cline
d16c8c9f0f ignore: update sdk 2025-11-21 01:25:06 -06:00
Aiden Cline
fffe20cbe5 add provider whitelist 2025-11-21 01:24:44 -06:00
Aiden Cline
f6da3c467b ignore: sync sdk 2025-11-21 01:04:02 -06:00
geril07
c0d9f21c0f feat: whitelist/blacklist config options for provider (#3416)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-21 01:01:30 -06:00
GitHub Action
a67b616139 chore: format code 2025-11-21 06:03:38 +00:00
opencode
2991547974 release: v1.0.85 2025-11-21 06:03:38 +00:00
Dax Raad
b59def2e4a hide gpt5 nano 2025-11-21 00:58:02 -05:00
opencode
d842353f39 release: v1.0.84 2025-11-21 05:55:03 +00:00
Dax Raad
d20ef569de tui: replace text shimmer with animated progress bar during model processing 2025-11-21 00:47:27 -05:00
Dax Raad
ca2b871810 tui: simplify popular providers list to show only top 6 instead of applying provider priority sorting 2025-11-21 00:32:21 -05:00
Dax
23ea8ba1ce Tui onboarding (#4569)
Co-authored-by: GitHub Action <action@github.com>
2025-11-21 00:21:06 -05:00
Zak
c417fec246 tweak: adjust invalid directory error message (#4567)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-20 22:36:07 -06:00
Aiden Cline
5413b16b57 fix: split not a function error 2025-11-20 22:33:59 -06:00
Spoon
43c021ed80 feat: add field to allow user only messages (#4554)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-20 19:13:42 -06:00
GitHub Action
3b005d29d7 chore: format code 2025-11-21 00:49:39 +00:00
opencode
635f70f477 release: v1.0.83 2025-11-21 00:49:39 +00:00
Aiden Cline
adbb6037ac fix: undefined err 2025-11-20 18:43:58 -06:00
opencode
598d6d00e4 release: v1.0.82 2025-11-20 22:44:37 +00:00
Aiden Cline
cf934357c9 fix: make use openrouter ai sdk package to fix interlevened thinking models 2025-11-20 16:32:44 -06:00
Jay
8063e645c7 docs: Clarify model provider recommendations in README
Updated the README to clarify model provider recommendations.
2025-11-20 17:21:19 -05:00
Aiden Cline
8ab206b443 tweak: navigate to child session if it is asking for permissions 2025-11-20 15:46:49 -06:00
Aiden Cline
ec5c96e10d Revert "Image tag fix for real this time (#4540)"
This reverts commit eb975bb89c.
2025-11-20 14:14:02 -06:00
Aiden Cline
d2a61290b9 Revert "ignore: write todo"
This reverts commit 5aa2078852.
2025-11-20 14:13:56 -06:00
Aiden Cline
10faf9e717 ignore: fix mdx 2025-11-20 14:07:25 -06:00
Aiden Cline
cba239bc8f change default child session cycle keybind to <leader>right, and <leader>left 2025-11-20 14:01:02 -06:00
jian
6f5e3ddfb3 chore: rm empty file (#4552) 2025-11-20 13:33:09 -06:00
GitHub Action
d412ba264a chore: format code 2025-11-20 19:17:06 +00:00
Aiden Cline
9780f2b792 docs: update model list 2025-11-20 13:16:27 -06:00
Aiden Cline
5aa2078852 ignore: write todo 2025-11-20 12:35:34 -06:00
shuv
eb975bb89c Image tag fix for real this time (#4540)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-20 12:34:39 -06:00
GitHub Action
9479fe3ce6 chore: format code 2025-11-20 17:35:43 +00:00
William Tan
4393cf8dbe tweak: Prefer VISUAL environment variable over EDITOR per Unix convention (#4549)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-20 11:27:16 -06:00
opencode
447a4ca8c3 release: v1.0.81 2025-11-20 17:16:31 +00:00
Aiden Cline
40ac2549ff fix: aur build 2025-11-20 11:04:09 -06:00
cc-bjojac
a9c56b813a Make the MAX_OUTPUT_LENGTH in bash.ts overridable by OPENCODE_EXPERIMENTAL_BASH_MAX_OUTPUT_LENGTH (#4497)
Co-authored-by: Björn Jacobs <bjoern.jacobs.ext@bundesanzeiger.de>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-20 10:45:13 -06:00
Haris Gušić
b1b73c9deb fix: Autocomplete with existing space after trigger (#4121)
Co-authored-by: GitHub Action <action@github.com>
2025-11-20 10:37:45 -06:00
Aiden Cline
774377330b fix: lockfile 2025-11-20 10:16:34 -06:00
processtrader
e7a157ef8f fix: replace ruby-lsp with rubocop for better LSP performance (#4543) 2025-11-20 09:54:47 -06:00
Frank
3989b9fc7f wip: zen 2025-11-20 10:31:35 -05:00
GitHub Action
8bfcdf4831 chore: format code 2025-11-20 14:55:06 +00:00
Frank
3632ba3785 zen: show token breakdown 2025-11-20 09:54:22 -05:00
Albert O'Shea
b7b3824d76 nix: update flake.lock as part of the github workflow (#4535)
Co-authored-by: Github Action <action@github.com>
2025-11-20 08:43:13 -06:00
Tommy D. Rossi
b12efb2023 fix: do not print ai sdk warnings (#4541)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-20 08:42:24 -06:00
Roberto Gongora
bd91cf220c docs: typo in PHP Intelephense documentation (#4545) 2025-11-20 08:41:31 -06:00
Asmae_ELAZRAK
9eb6731c21 docs: add cortecs docs (#4547) 2025-11-20 08:34:04 -06:00
GitHub Action
11373755d9 ignore: update download stats 2025-11-20 2025-11-20 12:04:55 +00:00
Aiden Cline
00b5e9f6ca chore: rm unused code 2025-11-20 00:10:51 -06:00
Aiden Cline
6b3f424e4d tweak: let user name export file 2025-11-19 23:58:40 -06:00
Aiden Cline
e7dfeec9c4 fix: make toast wrap 2025-11-19 22:50:27 -06:00
Aiden Cline
97893bd7e6 tweak: make /export go to cwd 2025-11-19 22:45:40 -06:00
Frank
bfefdb3752 zen: add gemini icon 2025-11-19 21:14:31 -05:00
Frank
12b79c581e zen: update gemini provider name 2025-11-19 20:58:22 -05:00
Frank
ac9b4c7ebf docs: add gemini 3 pricing 2025-11-19 20:50:43 -05:00
GitHub Action
208af232ff chore: format code 2025-11-20 01:27:50 +00:00
opencode
600c6b4973 release: v1.0.80 2025-11-20 01:27:49 +00:00
Dax Raad
61007a9b94 refactor: switch to Switch/Match pattern for assistant message status rendering 2025-11-19 20:18:15 -05:00
opencode
52fe1a5ac5 release: v1.0.79 2025-11-20 01:11:20 +00:00
althafdemiandra
468927e06a chore: bump ai-sdk to v5.0.97 (#4518)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-19 18:44:33 -06:00
Aiden Cline
61562dd9f0 make aur build check if u are glibc system or a musl system (#4519) 2025-11-19 18:36:33 -06:00
Github Action
c86dd91310 Update Nix hashes 2025-11-19 23:30:37 +00:00
Sebastian Herrlinger
9c85a37811 bump opentui version to v0.1.47
- fixing cursor issues with some graphemes in textarea
- proper suspend/resume
2025-11-20 00:28:25 +01:00
Aiden Cline
51bba6e634 tweak: default to disabling fetch timeout in provider options 2025-11-19 16:20:29 -06:00
Daniel Polito
e1089bc5de Adding LSP: PHP Intelephense (#4504)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-19 16:01:18 -06:00
Aiden Cline
618c654aa0 ignore: todo fix test case 2025-11-19 15:18:21 -06:00
Iljo
4703e859bd Add YAML language server support (#4508)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-19 14:47:04 -06:00
Aiden Cline
a1dc4ebbe4 ignore: flaky test be a lil less flaky plz 2025-11-19 14:46:06 -06:00
Aiden Cline
e4e6096510 ignore: fix hanging test 2025-11-19 14:38:12 -06:00
Aiden Cline
c472734933 tweak: make getUsage function handle missing usage data 2025-11-19 14:29:19 -06:00
Aiden Cline
9d068c20bb fix: openrouter ai sdk package support 2025-11-19 14:22:51 -06:00
Aiden Cline
48e4f2f45d tweak: add bun install retries 2025-11-19 13:04:20 -06:00
Aiden Cline
bbf4574476 fix: make external_directory permission wildcarding more sane 2025-11-19 12:55:02 -06:00
Adam
8bad513140 Revert "feat(cli): better install script output"
This reverts commit 24bb293136.
2025-11-19 12:44:35 -06:00
Aiden Cline
1ff5d888c2 fix: make bash tool use external_directory perm 2025-11-19 12:31:34 -06:00
Dax Raad
5d25758400 use bash description as task title 2025-11-19 13:23:29 -05:00
Dax
16fdc90976 fix: resolve issue 4475 (#4505) 2025-11-19 13:10:09 -05:00
Aiden Cline
793542230f tweak: bash description 2025-11-19 11:31:12 -06:00
Tommy D. Rossi
9de1242d9b fix: show reasoning summaries for gemini models (#4491)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-19 11:25:18 -06:00
Aiden Cline
b3afa84058 Revert "Added subagents to agents modal, non-selectable (#4460)"
This reverts commit 90044196bf.
2025-11-19 11:00:38 -06:00
Aiden Cline
024a10bbb5 ci: auto label nix 2025-11-19 10:51:11 -06:00
Adam
bef9ac96e2 fix(web): stats 2025-11-19 10:05:39 -06:00
Adam
24bb293136 feat(cli): better install script output 2025-11-19 09:30:41 -06:00
Adam
45180104fe fix(desktop): message animation 2025-11-19 06:04:20 -06:00
Adam
edd86e3fb7 fix(desktop): text part styling 2025-11-19 06:04:20 -06:00
Adam
4a72d57534 fix(desktop): pre styling 2025-11-19 06:04:19 -06:00
Aiden Cline
0068cb305f tweak: toast 2025-11-19 00:51:07 -06:00
opencode-agent[bot]
90044196bf Added subagents to agents modal, non-selectable (#4460)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-19 00:40:47 -06:00
Shantur Rathore
963a926db2 allow task tool to have resume capabilities (#4204)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-11-19 00:17:26 -06:00
Frank
0d3d48bb59 zen: fix cost in graph 2025-11-18 23:43:26 -05:00
GitHub Action
66eaba4bdc chore: format code 2025-11-19 01:02:57 +00:00
Dax Raad
21b6e5404e feat: add @opencode-ai/util package with utility functions 2025-11-18 20:02:10 -05:00
GitHub Action
a0fe59ab75 chore: format code 2025-11-18 23:49:29 +00:00
Aiden Cline
81ebf56cf1 feat: add top level lsp: false and formatter: false to allow disabling all formatters or lsps at once 2025-11-18 17:48:40 -06:00
opencode
429708e3d5 release: v1.0.78 2025-11-18 23:36:35 +00:00
shuv
d50f825c6d fix: pass model info to ReadTool to enable image support check (#4473)
Co-authored-by: GitHub Action <action@github.com>
2025-11-18 17:20:03 -06:00
K Whiteside
47bfae52c0 fix: permission checks for external_directory and doom_loop (#4433)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: AerionDyseti <AerionDyseti@users.noreply.github.com>
2025-11-18 17:18:23 -06:00
Frank
52cf9e3423 wip: zen 2025-11-18 17:42:48 -05:00
GitHub Action
a9b6debfa2 chore: format code 2025-11-18 22:24:29 +00:00
Eric Juden
d6bf475749 docs: Improving Plugin Documentation - Adding Events (#4438) 2025-11-18 16:23:46 -06:00
opencode
f22580e943 release: v1.0.77 2025-11-18 22:17:39 +00:00
Dax Raad
6d98db57c7 better gemini retry errors 2025-11-18 17:11:29 -05:00
OpeOginni
59f127a250 fix: allow for theme references (#4450) 2025-11-18 14:26:42 -06:00
Adam
3068e7dcf7 fix(desktop): animating too much 2025-11-18 14:24:26 -06:00
GitHub Action
f83d62191a chore: format code 2025-11-18 20:23:29 +00:00
Longlone
3b72857124 fix: update reasoningEffort logic for gpt-5.1 models in SessionPrompt-ensureTitle (#4456)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
2025-11-18 14:22:44 -06:00
opencode
68cd105d9d release: v1.0.76 2025-11-18 20:12:38 +00:00
Aiden Cline
e09af2cb4b fix windows bash tool issue 2025-11-18 14:06:45 -06:00
Adam
14bd3b1d30 chore(desktop): remove logging 2025-11-18 13:52:29 -06:00
Adam
3a9c2152f7 fix(desktop): reactivity issue on route change 2025-11-18 13:45:27 -06:00
Frank
7283bfa480 zen: gemini 2025-11-18 14:28:31 -05:00
opencode-agent[bot]
37d5099728 Added opencode agent list command to show all available agents with details. (#4446)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-11-18 13:25:53 -06:00
GitHub Action
d45fc030b2 chore: format code 2025-11-18 18:35:26 +00:00
Adam
c7042c807f fix(desktop): only animate response once 2025-11-18 12:34:34 -06:00
2075 changed files with 64991 additions and 47303 deletions

View File

@@ -1,57 +0,0 @@
#
# This file is intentionally in the wrong dir, will move and add later....
#
name: Guidelines Check
on:
# Disabled - uncomment to re-enable
# pull_request_target:
# types: [opened, synchronize]
jobs:
check-guidelines:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install opencode
run: curl -fsSL https://opencode.ai/install | bash
- name: Check PR guidelines compliance
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }'
run: |
opencode run -m anthropic/claude-sonnet-4-20250514 "A new pull request has been created: '${{ github.event.pull_request.title }}'
<pr-number>
${{ github.event.pull_request.number }}
</pr-number>
<pr-description>
${{ github.event.pull_request.body }}
</pr-description>
Please check all the code changes in this pull request against the guidelines in AGENTS.md file in this repository. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do
Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block.
Command MUST be like this.
```
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments \
-f 'body=[summary of issue]' -f 'commit_id=${{ github.event.pull_request.head.sha }}' -f 'path=[path-to-file]' -F "line=[line]" -f 'side=RIGHT'
```
Only create comments for actual violations. If the code follows all guidelines, don't run any gh commands."

View File

@@ -6,7 +6,7 @@ on:
jobs:
auto-label:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
issues: write
@@ -28,14 +28,14 @@ jobs:
const versionPattern = /[v]?1\.0\./i;
const isVersionRelated = versionPattern.test(title) || versionPattern.test(description);
// Check for "nix" keyword
const nixPattern = /\bnix\b/i;
const isNixRelated = nixPattern.test(title) || nixPattern.test(description);
const labels = [];
if (isWebRelated) {
// Add web label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ['web']
});
labels.push('web');
// Assign to adamdotdevin
await github.rest.issues.addAssignees({
@@ -46,10 +46,18 @@ jobs:
});
} else if (isVersionRelated) {
// Only add opentui if NOT web-related
labels.push('opentui');
}
if (isNixRelated) {
labels.push('nix');
}
if (labels.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ['opentui']
labels: labels
});
}

View File

@@ -11,12 +11,16 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
deploy:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-bun
- uses: actions/setup-node@v4
with:
node-version: "24"
- run: bun sst deploy --stage=${{ github.ref_name }}
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

View File

@@ -6,7 +6,7 @@ on:
jobs:
check-duplicates:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
issues: write
@@ -21,7 +21,7 @@ jobs:
- name: Check for duplicate issues
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENCODE_PERMISSION: |
{
@@ -55,4 +55,7 @@ jobs:
Feel free to ignore if none of these address your specific case.'
Additionally, if the issue mentions keybinds, keyboard shortcuts, or key bindings, please add a comment mentioning the pinned keybinds issue #4997:
'For keybind-related issues, please also check our pinned keybinds documentation: #4997'
If no clear duplicates are found, do not comment."

View File

@@ -10,7 +10,7 @@ on:
workflow_dispatch:
jobs:
format:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
steps:
@@ -18,6 +18,8 @@ jobs:
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
ref: ${{ github.event.pull_request.head.ref || github.ref_name }}
- name: Setup Bun
uses: ./.github/actions/setup-bun
@@ -27,3 +29,4 @@ jobs:
./script/format.ts
env:
CI: true
PUSH_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}

View File

@@ -6,7 +6,7 @@ on:
jobs:
notify:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Send nicely-formatted embed to Discord
uses: SethCohen/github-releases-to-discord@v1

View File

@@ -3,6 +3,8 @@ name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
@@ -11,7 +13,7 @@ jobs:
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
id-token: write
contents: read
@@ -21,9 +23,11 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./.github/actions/setup-bun
- name: Run opencode
uses: sst/opencode/github@latest
env:
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
with:
model: opencode/glm-4.6
model: opencode/claude-haiku-4-5

View File

@@ -14,7 +14,7 @@ permissions:
jobs:
publish:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v3
with:

View File

@@ -13,7 +13,7 @@ permissions:
jobs:
publish:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v3
with:

View File

@@ -25,7 +25,8 @@ permissions:
jobs:
publish:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.repository == 'sst/opencode' && github.ref == 'refs/heads/dev'
steps:
- uses: actions/checkout@v3
with:
@@ -61,6 +62,13 @@ jobs:
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish
run: |
./script/publish.ts
@@ -72,3 +80,103 @@ jobs:
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
publish-tauri:
continue-on-error: true
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
- host: ubuntu-24.04
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: apple-actions/import-codesign-certs@v2
if: ${{ runner.os == 'macOS' }}
with:
keychain: build
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Verify Certificate
if: ${{ runner.os == 'macOS' }}
run: |
CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application")
CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
echo "Certificate imported."
- name: Setup Apple API Key
if: ${{ runner.os == 'macOS' }}
run: |
echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8
- run: git fetch --force --tags
- uses: ./.github/actions/setup-bun
- name: install dependencies (ubuntu only)
if: startsWith(matrix.settings.host, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.settings.target }}
- uses: Swatinem/rust-cache@v2
with:
workspaces: packages/tauri/src-tauri
shared-key: ${{ matrix.settings.target }}
- name: Prepare
run: |
cd packages/tauri
bun ./scripts/prepare.ts
env:
OPENCODE_BUMP: ${{ inputs.bump }}
OPENCODE_VERSION: ${{ inputs.version }}
OPENCODE_CHANNEL: latest
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
RUST_TARGET: ${{ matrix.settings.target }}
GH_TOKEN: ${{ github.token }}
# Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released
- run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage
if: startsWith(matrix.settings.host, 'ubuntu')
- name: Build and upload artifacts
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_BUNDLER_NEW_APPIMAGE_FORMAT: true
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8
with:
projectPath: packages/tauri
uploadWorkflowArtifacts: true
tauriScript: ${{ (startsWith(matrix.settings.host, 'ubuntu') && 'cargo tauri') || '' }}
args: --target ${{ matrix.settings.target }}
updaterJsonPreferNsis: true
# releaseId: TODO

79
.github/workflows/review.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Guidelines Check
on:
issue_comment:
types: [created]
jobs:
check-guidelines:
if: |
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/review') &&
contains(fromJson('["OWNER","MEMBER"]'), github.event.comment.author_association)
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
pull-requests: write
steps:
- name: Get PR number
id: pr-number
run: |
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
fi
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install opencode
run: curl -fsSL https://opencode.ai/install | bash
- name: Get PR details
id: pr-details
run: |
gh api /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }} > pr_data.json
echo "title=$(jq -r .title pr_data.json)" >> $GITHUB_OUTPUT
echo "sha=$(jq -r .head.sha pr_data.json)" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check PR guidelines compliance
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }'
PR_TITLE: ${{ steps.pr-details.outputs.title }}
run: |
PR_BODY=$(jq -r .body pr_data.json)
opencode run -m anthropic/claude-opus-4-5 "A new pull request has been created: '${PR_TITLE}'
<pr-number>
${{ steps.pr-number.outputs.number }}
</pr-number>
<pr-description>
$PR_BODY
</pr-description>
Please check all the code changes in this pull request against the style guide, also look for any bugs if they exist. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do
When critiquing code against the style guide, be sure that the code is ACTUALLY in violation, don't complain about else statements if they already use early returns there. You may complain about excessive nesting though, regardless of else statement usage.
When critiquing code style don't be a zealot, we don't like "let" statements but sometimes they are the simpliest option, if someone does a bunch of nesting with let, they should consider using iife (see packages/opencode/src/util.iife.ts)
Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block.
Command MUST be like this.
\`\`\`
gh api \
--method POST \
-H \"Accept: application/vnd.github+json\" \
-H \"X-GitHub-Api-Version: 2022-11-28\" \
/repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }}/comments \
-f 'body=[summary of issue]' -f 'commit_id=${{ steps.pr-details.outputs.sha }}' -f 'path=[path-to-file]' -F \"line=[line]\" -f 'side=RIGHT'
\`\`\`
Only create comments for actual violations. If the code follows all guidelines, comment on the issue using gh cli: 'lgtm' AND NOTHING ELSE!!!!."

39
.github/workflows/sdk.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: sdk
on:
push:
branches-ignore:
- production
pull_request:
branches-ignore:
- production
workflow_dispatch:
jobs:
format:
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: run
run: |
bun ./packages/sdk/js/script/build.ts
(cd packages/opencode && bun dev generate > ../sdk/openapi.json)
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to commit"
exit 0
fi
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add -A
git commit -m "chore: regen sdk"
git push --no-verify
env:
CI: true

View File

@@ -1,17 +1,20 @@
name: snapshot
on:
workflow_dispatch:
push:
branches:
- dev
- fix-snapshot-2
- test-bedrock
- v0
- otui-diffs
- snapshot-*
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
publish:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v3
with:

View File

@@ -7,7 +7,7 @@ on:
jobs:
stats:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write

View File

@@ -8,7 +8,7 @@ on:
jobs:
zed:
name: Release Zed Extension
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v4
with:

View File

@@ -10,7 +10,7 @@ on:
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -28,9 +28,3 @@ jobs:
bun turbo test
env:
CI: true
- name: Check SDK is up to date
run: |
bun ./packages/sdk/js/script/build.ts
git diff --exit-code packages/sdk/js/src/gen packages/sdk/js/dist
continue-on-error: false

View File

@@ -7,7 +7,7 @@ on:
jobs:
typecheck:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -18,7 +18,8 @@ on:
jobs:
update:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: blacksmith-4vcpu-ubuntu-2404
env:
SYSTEM: x86_64-linux
@@ -28,6 +29,8 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: ${{ github.head_ref || github.ref_name }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Setup Nix
uses: DeterminateSystems/nix-installer-action@v20
@@ -37,10 +40,19 @@ jobs:
git config --global user.email "action@github.com"
git config --global user.name "Github Action"
- name: Update flake.lock
run: |
set -euo pipefail
echo "📦 Updating flake.lock..."
nix flake update
echo "✅ flake.lock updated successfully"
- name: Update node_modules hash
run: |
set -euo pipefail
echo "🔄 Updating node_modules hash..."
nix/scripts/update-hashes.sh
echo "✅ node_modules hash updated successfully"
- name: Commit hash changes
env:
@@ -48,6 +60,8 @@ jobs:
run: |
set -euo pipefail
echo "🔍 Checking for changes in tracked Nix files..."
summarize() {
local status="$1"
{
@@ -62,18 +76,27 @@ jobs:
echo "" >> "$GITHUB_STEP_SUMMARY"
}
FILES=(flake.nix nix/node-modules.nix nix/hashes.json)
FILES=(flake.lock flake.nix nix/node-modules.nix nix/hashes.json)
STATUS="$(git status --short -- "${FILES[@]}" || true)"
if [ -z "$STATUS" ]; then
echo "✅ No changes detected. Hashes are already up to date."
summarize "no changes"
echo "No changes to tracked Nix files. Hashes are already up to date."
exit 0
fi
echo "📝 Changes detected:"
echo "$STATUS"
echo "🔗 Staging files..."
git add "${FILES[@]}"
git commit -m "Update Nix hashes"
echo "💾 Committing changes..."
git commit -m "Update Nix flake.lock and hashes"
echo "✅ Changes committed"
BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}"
echo "🌳 Pulling latest from branch: $BRANCH"
git pull --rebase origin "$BRANCH"
echo "🚀 Pushing changes to branch: $BRANCH"
git push origin HEAD:"$BRANCH"
echo "✅ Changes pushed successfully"
summarize "committed $(git rev-parse --short HEAD)"

3
.gitignore vendored
View File

@@ -6,7 +6,6 @@ node_modules
.idea
.vscode
*~
openapi.json
playground
tmp
dist
@@ -17,3 +16,5 @@ dist
refs
Session.vim
opencode.json
a.out
target

View File

@@ -1,2 +1,9 @@
#!/bin/sh
# Check if bun version matches package.json
EXPECTED_VERSION=$(grep '"packageManager"' package.json | sed 's/.*"bun@\([^"]*\)".*/\1/')
CURRENT_VERSION=$(bun --version)
if [ "$CURRENT_VERSION" != "$EXPECTED_VERSION" ]; then
echo "Error: Bun version $CURRENT_VERSION does not match expected version $EXPECTED_VERSION from package.json"
exit 1
fi
bun typecheck

View File

@@ -1,6 +1,5 @@
---
description: Git commit and push
subtask: true
description: git commit and push
---
commit and push
@@ -22,3 +21,6 @@ WHAT was done.
do not do generic messages like "improved agent experience" be very specific
about what user facing changes were made
if there are changes do a git pull --rebase
if there are conflicts DO NOT FIX THEM. notify me and I will fix them

View File

@@ -1,8 +0,0 @@
---
description: hello world iaosd ioasjdoiasjd oisadjoisajd osiajd oisaj dosaij dsoajsajdaijdoisa jdoias jdoias jdoia jois jo jdois jdoias jdoias j djoasdj
---
hey there $ARGUMENTS
!`ls`
check out @README.md

View File

@@ -1,5 +1,5 @@
---
description: "Find issue(s) on github"
description: "find issue(s) on github"
model: opencode/claude-haiku-4-5
---

View File

@@ -0,0 +1,15 @@
---
description: Remove AI code slop
---
Check the diff against dev, and remove all AI generated slop introduced in this branch.
This includes:
- Extra comments that a human wouldn't add or is inconsistent with the rest of the file
- Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
- Casts to any to get around type issues
- Any other style that is inconsistent with the file
- Unnecessary emoji usage
Report at the end with only a 1-3 sentence summary of what you changed

View File

@@ -1,5 +1,5 @@
---
description: Spellcheck all markdown file changes
description: spellcheck all markdown file changes
---
Look at all the unstaged changes to markdown (.md, .mdx) files, pull out the lines that have changed, and check for spelling and grammar errors.

View File

@@ -1,6 +1,10 @@
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-openai-codex-auth"],
// "enterprise": {
// "url": "https://enterprise.dev.opencode.ai",
// },
"instructions": ["STYLE_GUIDE.md"],
"provider": {
"opencode": {
"options": {
@@ -8,4 +12,17 @@
},
},
},
"mcp": {
"exa": {
"type": "remote",
"url": "https://mcp.exa.ai/mcp",
},
"morph": {
"type": "local",
"command": ["bunx", "@morphllm/morphmcp"],
"environment": {
"ENABLED_TOOLS": "warp_grep",
},
},
},
}

1
.prettierignore Normal file
View File

@@ -0,0 +1 @@
sst-env.d.ts

View File

@@ -1,16 +1,3 @@
## IMPORTANT
- Try to keep things in one function unless composable or reusable
- DO NOT do unnecessary destructuring of variables
- DO NOT use `else` statements unless necessary
- DO NOT use `try`/`catch` if it can be avoided
- AVOID `try`/`catch` where possible
- AVOID `else` statements
- AVOID using `any` type
- AVOID `let` statements
- PREFER single word variable names where possible
- Use as many bun apis as possible like Bun.file()
## Debugging
- To test opencode in the `packages/opencode` directory you can run `bun dev`

View File

@@ -42,6 +42,8 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you
> [!NOTE]
> After touching `packages/opencode/src/server/server.ts`, run "./packages/sdk/js/script/build.ts" to regenerate the JS sdk.
Please try to follow the [style guide](./STYLE_GUIDE.md)
### Setting up a Debugger
Bun debugging is currently rough around the edges. We hope this guide helps you get set up and avoid some pain points.

View File

@@ -87,7 +87,7 @@ If you are working on a project that's related to OpenCode and is using "opencod
It's very similar to Claude Code in terms of capability. Here are the key differences:
- 100% open source
- Not coupled to any provider. Although Anthropic is recommended, OpenCode can be used with OpenAI, Google or even local models. As models evolve the gaps between them will close and pricing will drop so being provider-agnostic is important.
- Not coupled to any provider. Although we recommend the models we provide through [OpenCode Zen](https://opencode.ai/zen); OpenCode can be used with Claude, OpenAI, Google or even local models. As models evolve the gaps between them will close and pricing will drop so being provider-agnostic is important.
- Out of the box LSP support
- A focus on TUI. OpenCode is built by neovim users and the creators of [terminal.shop](https://terminal.shop); we are going to push the limits of what's possible in the terminal.
- A client/server architecture. This for example can allow OpenCode to run on your computer, while you can drive it remotely from a mobile app. Meaning that the TUI frontend is just one of the possible clients.

308
STATS.md
View File

@@ -1,146 +1,166 @@
# Download Stats
| Date | GitHub Downloads | npm Downloads | Total |
| ---------- | ----------------- | ----------------- | ------------------- |
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) |
| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) |
| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) |
| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) |
| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) |
| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) |
| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) |
| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) |
| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) |
| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) |
| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) |
| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) |
| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) |
| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) |
| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) |
| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) |
| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) |
| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) |
| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) |
| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) |
| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) |
| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) |
| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) |
| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) |
| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) |
| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) |
| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) |
| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) |
| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) |
| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) |
| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) |
| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) |
| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) |
| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) |
| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) |
| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) |
| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) |
| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) |
| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) |
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) |
| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) |
| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) |
| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) |
| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) |
| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) |
| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) |
| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) |
| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) |
| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) |
| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) |
| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) |
| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) |
| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) |
| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) |
| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) |
| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) |
| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) |
| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) |
| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) |
| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) |
| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) |
| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) |
| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) |
| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) |
| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) |
| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) |
| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) |
| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) |
| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) |
| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) |
| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) |
| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) |
| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) |
| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) |
| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) |
| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) |
| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) |
| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) |
| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) |
| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) |
| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) |
| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) |
| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) |
| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) |
| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) |
| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) |
| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) |
| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) |
| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) |
| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) |
| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) |
| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) |
| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) |
| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) |
| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) |
| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) |
| Date | GitHub Downloads | npm Downloads | Total |
| ---------- | ------------------ | ----------------- | ------------------- |
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) |
| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) |
| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) |
| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) |
| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) |
| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) |
| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) |
| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) |
| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) |
| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) |
| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) |
| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) |
| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) |
| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) |
| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) |
| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) |
| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) |
| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) |
| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) |
| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) |
| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) |
| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) |
| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) |
| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) |
| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) |
| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) |
| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) |
| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) |
| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) |
| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) |
| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) |
| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) |
| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) |
| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) |
| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) |
| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) |
| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) |
| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) |
| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) |
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) |
| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) |
| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) |
| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) |
| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) |
| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) |
| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) |
| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) |
| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) |
| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) |
| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) |
| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) |
| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) |
| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) |
| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) |
| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) |
| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) |
| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) |
| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) |
| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) |
| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) |
| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) |
| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) |
| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) |
| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) |
| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) |
| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) |
| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) |
| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) |
| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) |
| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) |
| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) |
| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) |
| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) |
| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) |
| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) |
| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) |
| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) |
| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) |
| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) |
| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) |
| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) |
| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) |
| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) |
| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) |
| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) |
| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) |
| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) |
| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) |
| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) |
| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) |
| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) |
| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) |
| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) |
| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) |
| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) |
| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) |
| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) |
| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) |
| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) |
| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) |
| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) |
| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) |
| 2025-11-25 | 869,423 (+12,690) | 817,339 (+13,306) | 1,686,762 (+25,996) |
| 2025-11-26 | 881,414 (+11,991) | 832,518 (+15,179) | 1,713,932 (+27,170) |
| 2025-11-27 | 893,960 (+12,546) | 846,180 (+13,662) | 1,740,140 (+26,208) |
| 2025-11-28 | 901,741 (+7,781) | 856,482 (+10,302) | 1,758,223 (+18,083) |
| 2025-11-29 | 908,689 (+6,948) | 863,361 (+6,879) | 1,772,050 (+13,827) |
| 2025-11-30 | 916,116 (+7,427) | 870,194 (+6,833) | 1,786,310 (+14,260) |
| 2025-12-01 | 925,898 (+9,782) | 876,500 (+6,306) | 1,802,398 (+16,088) |
| 2025-12-02 | 939,250 (+13,352) | 890,919 (+14,419) | 1,830,169 (+27,771) |
| 2025-12-03 | 952,249 (+12,999) | 903,713 (+12,794) | 1,855,962 (+25,793) |
| 2025-12-04 | 965,611 (+13,362) | 916,471 (+12,758) | 1,882,082 (+26,120) |
| 2025-12-05 | 977,996 (+12,385) | 930,616 (+14,145) | 1,908,612 (+26,530) |
| 2025-12-06 | 987,884 (+9,888) | 943,773 (+13,157) | 1,931,657 (+23,045) |
| 2025-12-07 | 994,046 (+6,162) | 951,425 (+7,652) | 1,945,471 (+13,814) |
| 2025-12-08 | 1,000,898 (+6,852) | 957,149 (+5,724) | 1,958,047 (+12,576) |

12
STYLE_GUIDE.md Normal file
View File

@@ -0,0 +1,12 @@
## Style Guide
- Try to keep things in one function unless composable or reusable
- DO NOT do unnecessary destructuring of variables
- DO NOT use `else` statements unless necessary
- DO NOT use `try`/`catch` if it can be avoided
- AVOID `try`/`catch` where possible
- AVOID `else` statements
- AVOID using `any` type
- AVOID `let` statements
- PREFER single word variable names where possible
- Use as many bun apis as possible like Bun.file()

0
a.out
View File

1636
bun.lock

File diff suppressed because it is too large Load Diff

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1762156382,
"narHash": "sha256-Yg7Ag7ov5+36jEFC1DaZh/12SEXo6OO3/8rqADRxiqs=",
"lastModified": 1764947035,
"narHash": "sha256-EYHSjVM4Ox4lvCXUMiKKs2vETUSL5mx+J2FfutM7T9w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7241bcbb4f099a66aafca120d37c65e8dda32717",
"rev": "a672be65651c80d3f592a89b3945466584a22069",
"type": "github"
},
"original": {

View File

@@ -30,6 +30,24 @@ Leave the following comment on a GitHub PR. opencode will implement the requeste
Delete the attachment from S3 when the note is removed /oc
```
#### Review specific code lines
Leave a comment directly on code lines in the PR's "Files" tab. opencode will automatically detect the file, line numbers, and diff context to provide precise responses.
```
[Comment on specific lines in Files tab]
/oc add error handling here
```
When commenting on specific lines, opencode receives:
- The exact file being reviewed
- The specific lines of code
- The surrounding diff context
- Line number information
This allows for more targeted requests without needing to specify file paths or line numbers manually.
## Installation
Run the following command in the terminal from your GitHub repo:
@@ -51,6 +69,8 @@ This will walk you through installing the GitHub app, creating the workflow, and
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
@@ -135,3 +155,9 @@ Replace the image URL `https://github.com/user-attachments/assets/xxxxxxxx` with
```
MOCK_EVENT='{"eventName":"issue_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"issue":{"number":4,"pull_request":{}},"comment":{"id":1,"body":"hey opencode, summarize thread"}}}'
```
### PR review comment event
```
MOCK_EVENT='{"eventName":"pull_request_review_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"pull_request":{"number":7},"comment":{"id":1,"body":"hey opencode, add error handling","path":"src/components/Button.tsx","diff_hunk":"@@ -45,8 +45,11 @@\n- const handleClick = () => {\n- console.log('clicked')\n+ const handleClick = useCallback(() => {\n+ console.log('clicked')\n+ doSomething()\n+ }, [doSomething])","line":47,"original_line":45,"position":10,"commit_id":"abc123","original_commit_id":"def456"}}}'
```

View File

@@ -13,6 +13,10 @@ inputs:
description: "Share the opencode session (defaults to true for public repos)"
required: false
prompt:
description: "Custom prompt to override the default prompt"
required: false
runs:
using: "composite"
steps:
@@ -27,3 +31,4 @@ runs:
env:
MODEL: ${{ inputs.model }}
SHARE: ${{ inputs.share }}
PROMPT: ${{ inputs.prompt }}

View File

@@ -5,7 +5,7 @@ import { graphql } from "@octokit/graphql"
import * as core from "@actions/core"
import * as github from "@actions/github"
import type { Context as GitHubContext } from "@actions/github/lib/context"
import type { IssueCommentEvent } from "@octokit/webhooks-types"
import type { IssueCommentEvent, PullRequestReviewCommentEvent } from "@octokit/webhooks-types"
import { createOpencodeClient } from "@opencode-ai/sdk"
import { spawn } from "node:child_process"
@@ -124,7 +124,7 @@ let exitCode = 0
type PromptFiles = Awaited<ReturnType<typeof getUserPrompt>>["promptFiles"]
try {
assertContextEvent("issue_comment")
assertContextEvent("issue_comment", "pull_request_review_comment")
assertPayloadKeyword()
await assertOpencodeConnected()
@@ -241,19 +241,43 @@ function createOpencode() {
}
function assertPayloadKeyword() {
const payload = useContext().payload as IssueCommentEvent
const payload = useContext().payload as IssueCommentEvent | PullRequestReviewCommentEvent
const body = payload.comment.body.trim()
if (!body.match(/(?:^|\s)(?:\/opencode|\/oc)(?=$|\s)/)) {
throw new Error("Comments must mention `/opencode` or `/oc`")
}
}
function getReviewCommentContext() {
const context = useContext()
if (context.eventName !== "pull_request_review_comment") {
return null
}
const payload = context.payload as PullRequestReviewCommentEvent
return {
file: payload.comment.path,
diffHunk: payload.comment.diff_hunk,
line: payload.comment.line,
originalLine: payload.comment.original_line,
position: payload.comment.position,
commitId: payload.comment.commit_id,
originalCommitId: payload.comment.original_commit_id,
}
}
async function assertOpencodeConnected() {
let retry = 0
let connected = false
do {
try {
await client.app.get<true>()
await client.app.log<true>({
body: {
service: "github-workflow",
level: "info",
message: "Prepare to react to Github Workflow event",
},
})
connected = true
break
} catch (e) {}
@@ -383,11 +407,24 @@ async function createComment() {
}
async function getUserPrompt() {
const context = useContext()
const payload = context.payload as IssueCommentEvent | PullRequestReviewCommentEvent
const reviewContext = getReviewCommentContext()
let prompt = (() => {
const payload = useContext().payload as IssueCommentEvent
const body = payload.comment.body.trim()
if (body === "/opencode" || body === "/oc") return "Summarize this thread"
if (body.includes("/opencode") || body.includes("/oc")) return body
if (body === "/opencode" || body === "/oc") {
if (reviewContext) {
return `Review this code change and suggest improvements for the commented lines:\n\nFile: ${reviewContext.file}\nLines: ${reviewContext.line}\n\n${reviewContext.diffHunk}`
}
return "Summarize this thread"
}
if (body.includes("/opencode") || body.includes("/oc")) {
if (reviewContext) {
return `${body}\n\nContext: You are reviewing a comment on file "${reviewContext.file}" at line ${reviewContext.line}.\n\nDiff context:\n${reviewContext.diffHunk}`
}
return body
}
throw new Error("Comments must mention `/opencode` or `/oc`")
})()

2
github/sst-env.d.ts vendored
View File

@@ -6,4 +6,4 @@
/// <reference path="../sst-env.d.ts" />
import "sst"
export {}
export {}

View File

@@ -97,8 +97,12 @@ export const stripeWebhook = new stripe.WebhookEndpoint("StripeWebhookEndpoint",
],
})
const ZEN_MODELS1 = new sst.Secret("ZEN_MODELS1")
const ZEN_MODELS2 = new sst.Secret("ZEN_MODELS2")
const ZEN_MODELS = [
new sst.Secret("ZEN_MODELS1"),
new sst.Secret("ZEN_MODELS2"),
new sst.Secret("ZEN_MODELS3"),
new sst.Secret("ZEN_MODELS4"),
]
const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY")
const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", {
properties: { value: auth.url.apply((url) => url!) },
@@ -112,6 +116,8 @@ const gatewayKv = new sst.cloudflare.Kv("GatewayKv")
// CONSOLE
////////////////
const bucket = new sst.cloudflare.Bucket("ZenData")
const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID")
const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY")
@@ -128,15 +134,15 @@ new sst.cloudflare.x.SolidStart("Console", {
domain,
path: "packages/console/app",
link: [
bucket,
database,
AUTH_API_URL,
STRIPE_WEBHOOK_SECRET,
STRIPE_SECRET_KEY,
ZEN_MODELS1,
ZEN_MODELS2,
EMAILOCTOPUS_API_KEY,
AWS_SES_ACCESS_KEY_ID,
AWS_SES_SECRET_ACCESS_KEY,
...ZEN_MODELS,
...($dev
? [
new sst.Secret("CLOUDFLARE_DEFAULT_ACCOUNT_ID", process.env.CLOUDFLARE_DEFAULT_ACCOUNT_ID!),

17
infra/enterprise.ts Normal file
View File

@@ -0,0 +1,17 @@
import { SECRET } from "./secret"
import { domain } from "./stage"
const storage = new sst.cloudflare.Bucket("EnterpriseStorage")
const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", {
domain: "enterprise." + domain,
path: "packages/enterprise",
buildCommand: "bun run build:cloudflare",
environment: {
OPENCODE_STORAGE_ADAPTER: "r2",
OPENCODE_STORAGE_ACCOUNT_ID: sst.cloudflare.DEFAULT_ACCOUNT_ID,
OPENCODE_STORAGE_ACCESS_KEY_ID: SECRET.R2AccessKey.value,
OPENCODE_STORAGE_SECRET_ACCESS_KEY: SECRET.R2SecretKey.value,
OPENCODE_STORAGE_BUCKET: storage.name,
},
})

4
infra/secret.ts Normal file
View File

@@ -0,0 +1,4 @@
export const SECRET = {
R2AccessKey: new sst.Secret("R2AccessKey", "unknown"),
R2SecretKey: new sst.Secret("R2SecretKey", "unknown"),
}

229
install
View File

@@ -2,49 +2,103 @@
set -euo pipefail
APP=opencode
MUTED='\033[0;2m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
ORANGE='\033[38;2;255;140;0m'
ORANGE='\033[38;5;214m'
NC='\033[0m' # No Color
requested_version=${VERSION:-}
raw_os=$(uname -s)
os=$(echo "$raw_os" | tr '[:upper:]' '[:lower:]')
# Normalize various Unix-like identifiers
case "$raw_os" in
Darwin*) os="darwin" ;;
Linux*) os="linux" ;;
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
esac
arch=$(uname -m)
esac
arch=$(uname -m)
if [[ "$arch" == "aarch64" ]]; then
arch="arm64"
elif [[ "$arch" == "x86_64" ]]; then
fi
if [[ "$arch" == "x86_64" ]]; then
arch="x64"
fi
filename="$APP-$os-$arch.zip"
if [ "$os" = "darwin" ] && [ "$arch" = "x64" ]; then
rosetta_flag=$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)
if [ "$rosetta_flag" = "1" ]; then
arch="arm64"
fi
fi
case "$filename" in
*"-linux-"*)
[[ "$arch" == "x64" || "$arch" == "arm64" ]] || exit 1
combo="$os-$arch"
case "$combo" in
linux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64)
;;
*"-darwin-"*)
[[ "$arch" == "x64" || "$arch" == "arm64" ]] || exit 1
;;
*"-windows-"*)
[[ "$arch" == "x64" ]] || exit 1
;;
*)
echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"
exit 1
*)
echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"
exit 1
;;
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
is_musl=true
fi
if command -v ldd >/dev/null 2>&1; then
if ldd --version 2>&1 | grep -qi musl; then
is_musl=true
fi
fi
fi
needs_baseline=false
if [ "$arch" = "x64" ]; then
if [ "$os" = "linux" ]; then
if ! grep -qi avx2 /proc/cpuinfo 2>/dev/null; then
needs_baseline=true
fi
fi
if [ "$os" = "darwin" ]; then
avx2=$(sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0)
if [ "$avx2" != "1" ]; then
needs_baseline=true
fi
fi
fi
target="$os-$arch"
if [ "$needs_baseline" = "true" ]; then
target="$target-baseline"
fi
if [ "$is_musl" = "true" ]; then
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
fi
INSTALL_DIR=$HOME/.opencode/bin
mkdir -p "$INSTALL_DIR"
@@ -67,8 +121,8 @@ print_message() {
local color=""
case $level in
info) color="${GREEN}" ;;
warning) color="${YELLOW}" ;;
info) color="${NC}" ;;
warning) color="${NC}" ;;
error) color="${RED}" ;;
esac
@@ -86,19 +140,119 @@ check_version() {
installed_version=$(echo $installed_version | awk '{print $2}')
if [[ "$installed_version" != "$specific_version" ]]; then
print_message info "Installed version: ${YELLOW}$installed_version."
print_message info "${MUTED}Installed version: ${NC}$installed_version."
else
print_message info "Version ${YELLOW}$specific_version${GREEN} already installed"
print_message info "${MUTED}Version ${NC}$specific_version${MUTED} already installed"
exit 0
fi
fi
}
unbuffered_sed() {
if echo | sed -u -e "" >/dev/null 2>&1; then
sed -nu "$@"
elif echo | sed -l -e "" >/dev/null 2>&1; then
sed -nl "$@"
else
local pad="$(printf "\n%512s" "")"
sed -ne "s/$/\\${pad}/" "$@"
fi
}
print_progress() {
local bytes="$1"
local length="$2"
[ "$length" -gt 0 ] || return 0
local width=50
local percent=$(( bytes * 100 / length ))
[ "$percent" -gt 100 ] && percent=100
local on=$(( percent * width / 100 ))
local off=$(( width - on ))
local filled=$(printf "%*s" "$on" "")
filled=${filled// /■}
local empty=$(printf "%*s" "$off" "")
empty=${empty// /・}
printf "\r${ORANGE}%s%s %3d%%${NC}" "$filled" "$empty" "$percent" >&4
}
download_with_progress() {
local url="$1"
local output="$2"
if [ -t 2 ]; then
exec 4>&2
else
exec 4>/dev/null
fi
local tmp_dir=${TMPDIR:-/tmp}
local basename="${tmp_dir}/opencode_install_$$"
local tracefile="${basename}.trace"
rm -f "$tracefile"
mkfifo "$tracefile"
# Hide cursor
printf "\033[?25l" >&4
trap "trap - RETURN; rm -f \"$tracefile\"; printf '\033[?25h' >&4; exec 4>&-" RETURN
(
curl --trace-ascii "$tracefile" -s -L -o "$output" "$url"
) &
local curl_pid=$!
unbuffered_sed \
-e 'y/ACDEGHLNORTV/acdeghlnortv/' \
-e '/^0000: content-length:/p' \
-e '/^<= recv data/p' \
"$tracefile" | \
{
local length=0
local bytes=0
while IFS=" " read -r -a line; do
[ "${#line[@]}" -lt 2 ] && continue
local tag="${line[0]} ${line[1]}"
if [ "$tag" = "0000: content-length:" ]; then
length="${line[2]}"
length=$(echo "$length" | tr -d '\r')
bytes=0
elif [ "$tag" = "<= recv" ]; then
local size="${line[3]}"
bytes=$(( bytes + size ))
if [ "$length" -gt 0 ]; then
print_progress "$bytes" "$length"
fi
fi
done
}
wait $curl_pid
local ret=$?
echo "" >&4
return $ret
}
download_and_install() {
print_message info "Downloading ${ORANGE}opencode ${GREEN}version: ${YELLOW}$specific_version ${GREEN}..."
print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}version: ${NC}$specific_version"
mkdir -p opencodetmp && cd opencodetmp
curl -# -L -o "$filename" "$url"
unzip -q "$filename"
if [[ "$os" == "windows" ]] || ! download_with_progress "$url" "$filename"; then
# Fallback to standard curl on Windows or if custom progress fails
curl -# -L -o "$filename" "$url"
fi
if [ "$os" = "linux" ]; then
tar -xzf "$filename"
else
unzip -q "$filename"
fi
mv opencode "$INSTALL_DIR"
chmod 755 "${INSTALL_DIR}/opencode"
cd .. && rm -rf opencodetmp
@@ -117,7 +271,7 @@ add_to_path() {
elif [[ -w $config_file ]]; then
echo -e "\n# opencode" >> "$config_file"
echo "$command" >> "$config_file"
print_message info "Successfully added ${ORANGE}opencode ${GREEN}to \$PATH in $config_file"
print_message info "${MUTED}Successfully added ${NC}opencode ${MUTED}to \$PATH in ${NC}$config_file"
else
print_message warning "Manually add the directory to $config_file (or similar):"
print_message info " $command"
@@ -191,3 +345,20 @@ if [ -n "${GITHUB_ACTIONS-}" ] && [ "${GITHUB_ACTIONS}" == "true" ]; then
echo "$INSTALL_DIR" >> $GITHUB_PATH
print_message info "Added $INSTALL_DIR to \$GITHUB_PATH"
fi
echo -e ""
echo -e "${MUTED}  ${NC} ▄ "
echo -e "${MUTED}█▀▀█ █▀▀█ █▀▀█ █▀▀▄ ${NC}█▀▀▀ █▀▀█ █▀▀█ █▀▀█"
echo -e "${MUTED}█░░█ █░░█ █▀▀▀ █░░█ ${NC}█░░░ █░░█ █░░█ █▀▀▀"
echo -e "${MUTED}▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀ ${NC}▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀"
echo -e ""
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 ""
echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/docs"
echo -e ""
echo -e ""

40
nix/bundle.ts Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bun
import solidPlugin from "./node_modules/@opentui/solid/scripts/solid-plugin"
import path from "path"
import fs from "fs"
const dir = process.cwd()
const parser = fs.realpathSync(path.join(dir, "node_modules/@opentui/core/parser.worker.js"))
const worker = "./src/cli/cmd/tui/worker.ts"
const version = process.env.OPENCODE_VERSION ?? "local"
const channel = process.env.OPENCODE_CHANNEL ?? "local"
fs.rmSync(path.join(dir, "dist"), { recursive: true, force: true })
const result = await Bun.build({
entrypoints: ["./src/index.ts", worker, parser],
outdir: "./dist",
target: "bun",
sourcemap: "none",
tsconfig: "./tsconfig.json",
plugins: [solidPlugin],
external: ["@opentui/core"],
define: {
OPENCODE_VERSION: `'${version}'`,
OPENCODE_CHANNEL: `'${channel}'`,
// Leave undefined so runtime picks bundled/dist worker or fallback in code.
OPENCODE_WORKER_PATH: "undefined",
OTUI_TREE_SITTER_WORKER_PATH: 'new URL("./cli/cmd/tui/parser.worker.js", import.meta.url).href',
},
})
if (!result.success) {
console.error("bundle failed")
for (const log of result.logs) console.error(log)
process.exit(1)
}
const parserOut = path.join(dir, "dist/src/cli/cmd/tui/parser.worker.js")
fs.mkdirSync(path.dirname(parserOut), { recursive: true })
await Bun.write(parserOut, Bun.file(parser))

View File

@@ -1,3 +1,3 @@
{
"nodeModules": "sha256-lAU5G92UJ998pKOd0EAt9gUa/HUXXvu6xAUdH2STmDo="
"nodeModules": "sha256-IzF5XDY09Z1p/8jgYIHhE/jpKPub15KKUpV+a/aKpuc="
}

View File

@@ -1,4 +1,4 @@
{ lib, stdenv, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }:
{ lib, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }:
args:
let
scripts = args.scripts;
@@ -28,66 +28,93 @@ stdenvNoCC.mkDerivation (finalAttrs: {
makeBinaryWrapper
];
configurePhase = ''
runHook preConfigure
cp -R ${finalAttrs.node_modules}/. .
runHook postConfigure
'';
env.MODELS_DEV_API_JSON = args.modelsDev;
env.OPENCODE_VERSION = args.version;
env.OPENCODE_CHANNEL = "stable";
dontConfigure = true;
buildPhase = ''
runHook preBuild
cp ${scripts + "/bun-build.ts"} bun-build.ts
cp -r ${finalAttrs.node_modules}/node_modules .
cp -r ${finalAttrs.node_modules}/packages .
substituteInPlace bun-build.ts \
--replace '@VERSION@' "${finalAttrs.version}"
(
cd packages/opencode
export BUN_COMPILE_TARGET=${args.target}
bun --bun bun-build.ts
chmod -R u+w ./node_modules
mkdir -p ./node_modules/@opencode-ai
rm -f ./node_modules/@opencode-ai/{script,sdk,plugin}
ln -s $(pwd)/../../packages/script ./node_modules/@opencode-ai/script
ln -s $(pwd)/../../packages/sdk/js ./node_modules/@opencode-ai/sdk
ln -s $(pwd)/../../packages/plugin ./node_modules/@opencode-ai/plugin
cp ${./bundle.ts} ./bundle.ts
chmod +x ./bundle.ts
bun run ./bundle.ts
)
runHook postBuild
'';
dontStrip = true;
installPhase = ''
runHook preInstall
cd packages/opencode
if [ ! -f opencode ]; then
echo "ERROR: opencode binary not found in $(pwd)"
ls -la
exit 1
fi
if [ ! -f opencode-worker.js ]; then
echo "ERROR: opencode worker bundle not found in $(pwd)"
ls -la
if [ ! -d dist ]; then
echo "ERROR: dist directory missing after bundle step"
exit 1
fi
install -Dm755 opencode $out/bin/opencode
install -Dm644 opencode-worker.js $out/bin/opencode-worker.js
if [ -f opencode-assets.manifest ]; then
while IFS= read -r asset; do
[ -z "$asset" ] && continue
if [ ! -f "$asset" ]; then
echo "ERROR: referenced asset \"$asset\" missing"
exit 1
fi
install -Dm644 "$asset" "$out/bin/$(basename "$asset")"
done < opencode-assets.manifest
mkdir -p $out/lib/opencode
cp -r dist $out/lib/opencode/
chmod -R u+w $out/lib/opencode/dist
# Select bundled worker assets deterministically (sorted find output)
worker_file=$(find "$out/lib/opencode/dist" -type f \( -path '*/tui/worker.*' -o -name 'worker.*' \) | sort | head -n1)
parser_worker_file=$(find "$out/lib/opencode/dist" -type f -name 'parser.worker.*' | sort | head -n1)
if [ -z "$worker_file" ]; then
echo "ERROR: bundled worker not found"
exit 1
fi
main_wasm=$(printf '%s\n' "$out"/lib/opencode/dist/tree-sitter-*.wasm | sort | head -n1)
wasm_list=$(find "$out/lib/opencode/dist" -maxdepth 1 -name 'tree-sitter-*.wasm' -print)
for patch_file in "$worker_file" "$parser_worker_file"; do
[ -z "$patch_file" ] && continue
[ ! -f "$patch_file" ] && continue
if [ -n "$wasm_list" ] && grep -q 'tree-sitter' "$patch_file"; then
# Rewrite wasm references to absolute store paths to avoid runtime resolve failures.
bun --bun ${scripts + "/patch-wasm.ts"} "$patch_file" "$main_wasm" $wasm_list
fi
done
mkdir -p $out/lib/opencode/node_modules
cp -r ../../node_modules/.bun $out/lib/opencode/node_modules/
mkdir -p $out/lib/opencode/node_modules/@opentui
mkdir -p $out/bin
makeWrapper ${bun}/bin/bun $out/bin/opencode \
--add-flags "run" \
--add-flags "$out/lib/opencode/dist/src/index.js" \
--prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]} \
--argv0 opencode
runHook postInstall
'';
postFixup = ''
wrapProgram "$out/bin/opencode" --prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]}
postInstall = ''
for pkg in $out/lib/opencode/node_modules/.bun/@opentui+core-* $out/lib/opencode/node_modules/.bun/@opentui+solid-* $out/lib/opencode/node_modules/.bun/@opentui+core@* $out/lib/opencode/node_modules/.bun/@opentui+solid@*; do
if [ -d "$pkg" ]; then
pkgName=$(basename "$pkg" | sed 's/@opentui+\([^@]*\)@.*/\1/')
ln -sf ../.bun/$(basename "$pkg")/node_modules/@opentui/$pkgName \
$out/lib/opencode/node_modules/@opentui/$pkgName
fi
done
'';
dontFixup = true;
meta = {
description = "AI coding agent built for the terminal";
longDescription = ''

View File

@@ -24,15 +24,13 @@ for (const entry of directories) {
if (!info.isDirectory()) {
continue
}
const marker = entry.lastIndexOf("@")
if (marker <= 0) {
const parsed = parseEntry(entry)
if (!parsed) {
continue
}
const slug = entry.slice(0, marker).replace(/\+/g, "/")
const version = entry.slice(marker + 1)
const list = versions.get(slug) ?? []
list.push({ dir: full, version, label: entry })
versions.set(slug, list)
const list = versions.get(parsed.name) ?? []
list.push({ dir: full, version: parsed.version, label: entry })
versions.set(parsed.name, list)
}
const semverModule = (await import(join(bunRoot, "node_modules/semver"))) as
@@ -79,6 +77,12 @@ for (const [slug, entry] of Array.from(selections.entries()).sort((a, b) => a[0]
await mkdir(parent, { recursive: true })
const linkPath = join(parent, leaf)
const desired = join(entry.dir, "node_modules", slug)
const exists = await lstat(desired)
.then((info) => info.isDirectory())
.catch(() => false)
if (!exists) {
continue
}
const relativeTarget = relative(parent, desired)
const resolved = relativeTarget.length === 0 ? "." : relativeTarget
await rm(linkPath, { recursive: true, force: true })
@@ -94,3 +98,16 @@ for (const line of rewrites.slice(0, 20)) {
if (rewrites.length > 20) {
console.log(" ...")
}
function parseEntry(label: string) {
const marker = label.startsWith("@") ? label.indexOf("@", 1) : label.indexOf("@")
if (marker <= 0) {
return null
}
const name = label.slice(0, marker).replace(/\+/g, "/")
const version = label.slice(marker + 1)
if (!name || !version) {
return null
}
return { name, version }
}

39
nix/scripts/patch-wasm.ts Normal file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env bun
import fs from "fs"
import path from "path"
/**
* Rewrite tree-sitter wasm references inside a JS file to absolute paths.
* argv: [node, script, file, mainWasm, ...wasmPaths]
*/
const [, , file, mainWasm, ...wasmPaths] = process.argv
if (!file || !mainWasm) {
console.error("usage: patch-wasm <file> <mainWasm> [wasmPaths...]")
process.exit(1)
}
const content = fs.readFileSync(file, "utf8")
const byName = new Map<string, string>()
for (const wasm of wasmPaths) {
const name = path.basename(wasm)
byName.set(name, wasm)
}
let next = content
for (const [name, wasmPath] of byName) {
next = next.replaceAll(name, wasmPath)
}
next = next.replaceAll("tree-sitter.wasm", mainWasm).replaceAll("web-tree-sitter/tree-sitter.wasm", mainWasm)
// Collapse any relative prefixes before absolute store paths (e.g., "../../../..//nix/store/...")
next = next.replace(/(\.\/)+/g, "./")
next = next.replace(/(\.\.\/)+\/?(\/nix\/store[^"']+)/g, "/$2")
next = next.replace(/(["'])\/{2,}(\/nix\/store[^"']+)(["'])/g, "$1/$2$3")
next = next.replace(/(["'])\/\/(nix\/store[^"']+)(["'])/g, "$1/$2$3")
if (next !== content) fs.writeFileSync(file, next)

View File

@@ -4,12 +4,13 @@
"description": "AI-powered development tool",
"private": true,
"type": "module",
"packageManager": "bun@1.3.2",
"packageManager": "bun@1.3.3",
"scripts": {
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
"typecheck": "bun turbo typecheck",
"prepare": "husky",
"random": "echo 'Random script'"
"random": "echo 'Random script'",
"hello": "echo 'Hello World!'"
},
"workspaces": {
"packages": [
@@ -19,33 +20,37 @@
"packages/slack"
],
"catalog": {
"@types/bun": "1.3.0",
"@types/bun": "1.3.3",
"@hono/zod-validator": "0.4.2",
"ulid": "3.0.1",
"@kobalte/core": "0.13.11",
"@types/luxon": "3.7.1",
"@types/node": "22.13.9",
"@tsconfig/node22": "22.0.2",
"@tsconfig/bun": "1.0.9",
"@cloudflare/workers-types": "4.20251008.0",
"@openauthjs/openauth": "0.0.0-20250322224806",
"@pierre/precision-diffs": "0.4.4",
"@solidjs/meta": "0.29.4",
"@pierre/precision-diffs": "0.6.0-beta.10",
"@tailwindcss/vite": "4.1.11",
"diff": "8.0.2",
"ai": "5.0.8",
"hono": "4.7.10",
"ai": "5.0.97",
"hono": "4.10.7",
"hono-openapi": "1.1.2",
"fuzzysort": "3.1.0",
"luxon": "3.6.1",
"typescript": "5.8.2",
"@typescript/native-preview": "7.0.0-dev.20251014.1",
"@typescript/native-preview": "7.0.0-dev.20251207.1",
"zod": "4.1.8",
"remeda": "2.26.0",
"solid-js": "1.9.9",
"solid-list": "0.3.0",
"tailwindcss": "4.1.11",
"virtua": "0.42.3",
"vite": "7.1.4",
"vite-plugin-solid": "2.11.8"
"@solidjs/meta": "0.29.4",
"@solidjs/router": "0.15.4",
"@solidjs/start": "https://pkg.pr.new/@solidjs/start@dfb2020",
"solid-js": "1.9.10",
"vite-plugin-solid": "2.11.10"
}
},
"devDependencies": {
@@ -56,8 +61,10 @@
"turbo": "2.5.6"
},
"dependencies": {
"@aws-sdk/client-s3": "3.933.0",
"@opencode-ai/script": "workspace:*",
"@opencode-ai/sdk": "workspace:*"
"@opencode-ai/sdk": "workspace:*",
"typescript": "catalog:"
},
"repository": {
"type": "git",
@@ -76,11 +83,11 @@
"tree-sitter-bash",
"web-tree-sitter"
],
"patchedDependencies": {
"@solidjs/start@1.1.7": "patches/@solidjs%2Fstart@1.1.7.patch"
},
"overrides": {
"@types/bun": "catalog:",
"@types/node": "catalog:"
},
"patchedDependencies": {
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch"
}
}

View File

@@ -3,7 +3,6 @@ dist
.output
.vercel
.netlify
.vinxi
app.config.timestamp_*.js
# Environment

View File

@@ -1,23 +0,0 @@
import { defineConfig } from "@solidjs/start/config"
export default defineConfig({
middleware: "./src/middleware.ts",
vite: {
server: {
allowedHosts: true,
},
build: {
rollupOptions: {
external: ["cloudflare:workers"],
},
minify: false,
},
},
server: {
compatibilityDate: "2024-09-19",
preset: "cloudflare_module",
cloudflare: {
nodeCompat: true,
},
},
})

View File

@@ -1,15 +1,16 @@
{
"name": "@opencode-ai/console-app",
"version": "1.0.137",
"type": "module",
"scripts": {
"typecheck": "tsgo --noEmit",
"dev": "vinxi dev --host 0.0.0.0",
"dev": "vite dev --host 0.0.0.0",
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
"build": "./script/generate-sitemap.ts && vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
"start": "vinxi start",
"version": "1.0.75"
"build": "./script/generate-sitemap.ts && vite build && ../../opencode/script/schema.ts ./.output/public/config.json",
"start": "vite start"
},
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@ibm/plex": "6.4.1",
"@jsx-email/render": "1.1.1",
"@kobalte/core": "catalog:",
@@ -17,17 +18,20 @@
"@opencode-ai/console-core": "workspace:*",
"@opencode-ai/console-mail": "workspace:*",
"@opencode-ai/console-resource": "workspace:*",
"@solidjs/meta": "^0.29.4",
"@solidjs/router": "^0.15.0",
"@solidjs/start": "^1.1.0",
"@opencode-ai/ui": "workspace:*",
"@solidjs/meta": "catalog:",
"@solidjs/router": "catalog:",
"@solidjs/start": "catalog:",
"chart.js": "4.5.1",
"nitro": "3.0.1-alpha.1",
"solid-js": "catalog:",
"vinxi": "^0.5.7",
"vite": "catalog:",
"zod": "catalog:"
},
"devDependencies": {
"@typescript/native-preview": "catalog:",
"typescript": "catalog:",
"@typescript/native-preview": "catalog:"
"wrangler": "4.50.0"
},
"engines": {
"node": ">=22"

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/apple-touch-icon.png

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/favicon-96x96.png

View File

@@ -1,23 +0,0 @@
<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="400" height="400" fill="#FDFCFC"/>
<path d="M96 122.001V70.001H148V122.001H96Z" fill="#17181C"/>
<path d="M148.004 122.001V70.001H200.004V122.001H148.004Z" fill="#17181C"/>
<path d="M200.008 122.001V70.001H252.008V122.001H200.008Z" fill="#17181C"/>
<path d="M251.996 122.001V70.001H303.996V122.001H251.996Z" fill="#17181C"/>
<path d="M251.996 173.988V121.988H303.996V173.988H251.996Z" fill="#17181C"/>
<path d="M96 225.998V173.998H148V225.998H96Z" fill="#CFCECD"/>
<rect width="52" height="52" transform="translate(148.004 173.998)" fill="#17181C"/>
<path d="M148.004 225.998V173.998H200.004V225.998H148.004Z" fill="#17181C" fill-opacity="0.1"/>
<path d="M200.008 225.998V173.998H252.008V225.998H200.008Z" fill="#17181C"/>
<path d="M252.016 225.998V173.998H304.016V225.998H252.016Z" fill="#CFCECD"/>
<rect width="52" height="52" transform="translate(96 226.002)" fill="#17181C"/>
<path d="M96 278.002V226.002H148V278.002H96Z" fill="#17181C" fill-opacity="0.1"/>
<rect width="52" height="52" transform="translate(148.004 226.002)" fill="white"/>
<path d="M148.004 278.002V226.002H200.004V278.002H148.004Z" fill="#CFCECD"/>
<path d="M200.008 278.002V226.002H252.008V278.002H200.008Z" fill="#CFCECD"/>
<path d="M252.016 278.002V226.002H304.016V278.002H252.016Z" fill="#CFCECD"/>
<path d="M96 330.012V278.012H148V330.012H96Z" fill="#17181C"/>
<path d="M148.004 330.012V278.012H200.004V330.012H148.004Z" fill="#17181C"/>
<path d="M200.008 329.99V277.99H252.008V329.99H200.008Z" fill="#17181C"/>
<path d="M251.996 330.012V278.012H303.996V330.012H251.996Z" fill="#17181C"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/favicon.ico

View File

@@ -1,4 +0,0 @@
<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="400" height="400" fill="#0E0E0E"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M312 340H88V60H312V340ZM256 116H144V284H256V116Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 269 B

After

Width:  |  Height:  |  Size: 42 B

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/favicon.svg

Before

Width:  |  Height:  |  Size: 269 B

After

Width:  |  Height:  |  Size: 42 B

View File

@@ -2,4 +2,5 @@ User-agent: *
Allow: /
# Disallow shared content pages
Disallow: /s/
Disallow: /s/
Disallow: /share/

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/site.webmanifest

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 50 B

View File

@@ -0,0 +1 @@
../../../ui/src/assets/images/social-share-zen.png

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 50 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 46 B

View File

@@ -0,0 +1 @@
../../../ui/src/assets/images/social-share.png

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 46 B

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/web-app-manifest-192x192.png

View File

@@ -0,0 +1 @@
../../../ui/src/assets/favicon/web-app-manifest-512x512.png

View File

@@ -1,7 +1,8 @@
import { MetaProvider, Title, Meta } from "@solidjs/meta"
import { Router } from "@solidjs/router"
import { FileRoutes } from "@solidjs/start/router"
import { ErrorBoundary, Suspense } from "solid-js"
import { Suspense } from "solid-js"
import { Favicon } from "@opencode-ai/ui/favicon"
import "@ibm/plex/css/ibm-plex.css"
import "./app.css"
@@ -13,6 +14,7 @@ export default function App() {
<MetaProvider>
<Title>opencode</Title>
<Meta name="description" content="OpenCode - The AI coding agent built for the terminal." />
<Favicon />
<Suspense>{props.children}</Suspense>
</MetaProvider>
)}

View File

@@ -202,6 +202,14 @@ export function IconZai(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
)
}
export function IconGemini(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 50 50" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M49.04,24.001l-1.082-0.043h-0.001C36.134,23.492,26.508,13.866,26.042,2.043L25.999,0.96C25.978,0.424,25.537,0,25,0 s-0.978,0.424-0.999,0.96l-0.043,1.083C23.492,13.866,13.866,23.492,2.042,23.958L0.96,24.001C0.424,24.022,0,24.463,0,25 c0,0.537,0.424,0.978,0.961,0.999l1.082,0.042c11.823,0.467,21.449,10.093,21.915,21.916l0.043,1.083C24.022,49.576,24.463,50,25,50 s0.978-0.424,0.999-0.96l0.043-1.083c0.466-11.823,10.092-21.449,21.915-21.916l1.082-0.042C49.576,25.978,50,25.537,50,25 C50,24.463,49.576,24.022,49.04,24.001z"></path>
</svg>
)
}
export function IconStealth(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 18" fill="none">
@@ -228,3 +236,14 @@ export function IconChevronRight(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
</svg>
)
}
export function IconBreakdown(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M2 12L2 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M6 12L6 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M10 12L10 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M14 12L14 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
)
}

View File

@@ -9,8 +9,8 @@ export const config = {
github: {
repoUrl: "https://github.com/sst/opencode",
starsFormatted: {
compact: "30K",
full: "30,000",
compact: "35K",
full: "35,000",
},
},
@@ -22,8 +22,8 @@ export const config = {
// Static stats (used on landing page)
stats: {
contributors: "250",
commits: "3,500",
monthlyUsers: "300,000",
contributors: "350",
commits: "5,000",
monthlyUsers: "400,000",
},
} as const

View File

@@ -1,4 +1,4 @@
import { useSession } from "vinxi/http"
import { useSession } from "@solidjs/start/http"
export interface AuthSession {
account?: Record<

View File

@@ -9,7 +9,6 @@ export default createHandler(
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.svg" />
<meta property="og:image" content="/social-share.png" />
<meta property="twitter:image" content="/social-share.png" />
{assets}

View File

@@ -1 +1,5 @@
/// <reference types="@solidjs/start/env" />
export declare module "@solidjs/start/server" {
export type APIEvent = { request: Request }
}

View File

@@ -1,5 +1,5 @@
import { defineMiddleware } from "vinxi/http"
import { createMiddleware } from "@solidjs/start/middleware"
export default defineMiddleware({
export default createMiddleware({
onBeforeResponse() {},
})

View File

@@ -36,6 +36,7 @@ ${body.email}`.trim()
to: "contact@anoma.ly",
subject: `Enterprise Inquiry from ${body.name}`,
body: emailContent,
replyTo: body.email,
})
return Response.json({ success: true, message: "Form submitted successfully" }, { status: 200 })

View File

@@ -19,6 +19,7 @@ export async function GET(input: APIEvent) {
return {
...value,
account: {
...value.account,
[id]: {
id,
email: decoded.subject.properties.email,

View File

@@ -0,0 +1,17 @@
import { redirect } from "@solidjs/router"
import { APIEvent } from "@solidjs/start"
import { useAuthSession } from "~/context/auth.session"
export async function GET(event: APIEvent) {
const auth = await useAuthSession()
const current = auth.data.current
if (current)
await auth.update((val) => {
delete val.account?.[current]
const first = Object.keys(val.account ?? {})[0]
val.current = first
event!.locals.actor = undefined
return val
})
return redirect("/zen")
}

View File

@@ -0,0 +1,7 @@
import { APIEvent } from "@solidjs/start"
import { useAuthSession } from "~/context/auth.session"
export async function GET(input: APIEvent) {
const session = await useAuthSession()
return Response.json(session.data)
}

View File

@@ -338,6 +338,11 @@ body {
}
}
[data-slot="installation-instructions"] {
color: var(--color-text-strong);
margin-bottom: 8px;
}
[data-slot="installation"] {
width: 100%;
max-width: 100%;
@@ -348,6 +353,11 @@ body {
}
}
[data-slot="installation-options"] {
font-size: 13px;
margin-top: 12px;
}
[data-component="tabs"] {
[data-slot="tablist"] {
display: flex;
@@ -480,10 +490,10 @@ body {
}
h1 {
font-size: 28px;
font-size: 38px;
color: var(--color-text-strong);
font-weight: 500;
margin-bottom: 16px;
margin-bottom: 8px;
@media (max-width: 60rem) {
font-size: 22px;
@@ -492,7 +502,7 @@ body {
p {
color: var(--color-text);
margin-bottom: 24px;
margin-bottom: 40px;
max-width: 82%;
@media (max-width: 50rem) {
@@ -607,6 +617,25 @@ body {
padding: var(--vertical-padding) var(--padding);
color: var(--color-text);
a {
background: var(--color-background-strong);
padding: 8px 12px 8px 20px;
color: var(--color-text-inverted);
border: none;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
margin-top: 40px;
display: flex;
width: fit-content;
gap: 12px;
text-decoration: none;
}
a:hover {
background: var(--color-background-strong-hover);
}
ul {
padding: 0;
li {

View File

@@ -1,6 +1,6 @@
import "./index.css"
import { Title, Meta, Link } from "@solidjs/meta"
import { HttpHeader } from "@solidjs/start"
// import { HttpHeader } from "@solidjs/start"
import video from "../asset/lander/opencode-min.mp4"
import videoPoster from "../asset/lander/opencode-poster.png"
import { IconCopy, IconCheck } from "../component/icon"
@@ -42,10 +42,9 @@ export default function Home() {
return (
<main data-page="opencode">
<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />
<Title>OpenCode | The AI coding agent built for the terminal</Title>
{/*<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />*/}
<Title>OpenCode | The open source AI coding agent</Title>
<Link rel="canonical" href={config.baseUrl} />
<Link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<Meta property="og:image" content="/social-share.png" />
<Meta name="twitter:image" content="/social-share.png" />
<div data-component="container">
@@ -57,23 +56,13 @@ export default function Home() {
<a data-slot="releases" href={release()?.url ?? `${config.github.repoUrl}/releases`} target="_blank">
Whats new in {release()?.name ?? "the latest release"}
</a>
<h1>The AI coding agent built for the terminal</h1>
<h1>The open source coding agent</h1>
<p>
OpenCode is fully open source, giving you control and freedom to use any provider, any model, and any
editor.
OpenCode includes free models or connect from any provider to <br />
use other models, including Claude, GPT, Gemini and more.
</p>
<a href="/docs">
<span>Read docs </span>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="square"
/>
</svg>
</a>
</div>
<p data-slot="installation-instructions">Install and use. No account, no email, and no credit card.</p>
<div data-slot="installation">
<Tabs
as="section"
@@ -152,6 +141,11 @@ export default function Home() {
</div>
</Tabs>
</div>
<p data-slot="installation-options">
Available in terminal, web, and desktop (coming soon).
<br />
Extensions for VS Code, Cursor, Windsurf, and more.
</p>
</section>
<section data-component="video">
@@ -209,6 +203,17 @@ export default function Home() {
</div>
</li>
</ul>
<a href="/docs">
<span>Read docs </span>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="square"
/>
</svg>
</a>
</section>
<section data-component="growth">

View File

@@ -0,0 +1,7 @@
export async function GET() {
const response = await fetch(
"https://raw.githubusercontent.com/sst/opencode/refs/heads/dev/packages/sdk/openapi.json",
)
const json = await response.json()
return json
}

View File

@@ -12,6 +12,7 @@
[data-slot="item"] {
color: var(--color-danger);
text-decoration: none;
}
}
}

View File

@@ -1,4 +1,4 @@
import { action, redirect } from "@solidjs/router"
import { action } from "@solidjs/router"
import { getRequestEvent } from "solid-js/web"
import { useAuthSession } from "~/context/auth.session"
import { Dropdown } from "~/component/dropdown"
@@ -17,18 +17,15 @@ const logout = action(async () => {
event!.locals.actor = undefined
return val
})
throw redirect("/zen")
})
}, "auth.logout")
export function UserMenu(props: { email: string | null | undefined }) {
return (
<div data-component="user-menu">
<Dropdown trigger={props.email ?? ""} align="right">
<form action={logout} method="post">
<button type="submit" formaction={logout} data-slot="item">
Logout
</button>
</form>
<a href="/auth/logout" data-slot="item">
Logout
</a>
</Dropdown>
</div>
)

View File

@@ -14,7 +14,7 @@ import "./workspace-picker.css"
const getWorkspaces = query(async () => {
"use server"
return withActor(async () => {
return Database.transaction((tx) =>
return Database.use((tx) =>
tx
.select({
id: WorkspaceTable.id,

View File

@@ -6,7 +6,6 @@ import { UserMenu } from "./user-menu"
import { withActor } from "~/context/auth.withActor"
import { User } from "@opencode-ai/console-core/user.js"
import { Actor } from "@opencode-ai/console-core/actor.js"
import { Link } from "@solidjs/meta"
const getUserEmail = query(async (workspaceID: string) => {
"use server"
@@ -22,7 +21,6 @@ export default function WorkspaceLayout(props: RouteSectionProps) {
const userEmail = createAsync(() => getUserEmail(params.id!))
return (
<main data-page="workspace">
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
<header data-component="workspace-header">
<div data-slot="header-brand">
<A href="/" data-component="site-title">

View File

@@ -1,9 +1,9 @@
import { and, Database, eq, gte, inArray, isNull, lte, or, sql } from "@opencode-ai/console-core/drizzle/index.js"
import { and, Database, eq, gte, inArray, isNull, lte, or, sql, sum } from "@opencode-ai/console-core/drizzle/index.js"
import { UsageTable } from "@opencode-ai/console-core/schema/billing.sql.js"
import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
import { AuthTable } from "@opencode-ai/console-core/schema/auth.sql.js"
import { createAsync, query, useParams } from "@solidjs/router"
import { useParams } from "@solidjs/router"
import { createEffect, createMemo, onCleanup, Show, For } from "solid-js"
import { createStore } from "solid-js/store"
import { withActor } from "~/context/auth.withActor"
@@ -35,7 +35,7 @@ async function getCosts(workspaceID: string, year: number, month: number) {
.select({
date: sql<string>`DATE(${UsageTable.timeCreated})`,
model: UsageTable.model,
totalCost: sql<number>`SUM(${UsageTable.cost})`,
totalCost: sum(UsageTable.cost),
keyId: UsageTable.keyID,
})
.from(UsageTable)
@@ -46,7 +46,13 @@ async function getCosts(workspaceID: string, year: number, month: number) {
lte(UsageTable.timeCreated, endDate),
),
)
.groupBy(sql`DATE(${UsageTable.timeCreated})`, UsageTable.model, UsageTable.keyID),
.groupBy(sql`DATE(${UsageTable.timeCreated})`, UsageTable.model, UsageTable.keyID)
.then((x) =>
x.map((r) => ({
...r,
totalCost: r.totalCost ? parseInt(r.totalCost) : 0,
})),
),
)
// Get unique key IDs from usage
@@ -88,8 +94,6 @@ async function getCosts(workspaceID: string, year: number, month: number) {
}, workspaceID)
}
const queryCosts = query(getCosts, "costs.get")
const MODEL_COLORS: Record<string, string> = {
"claude-sonnet-4-5": "#D4745C",
"claude-sonnet-4": "#E8B4A4",
@@ -152,32 +156,27 @@ export function GraphSection() {
model: null as string | null,
modelDropdownOpen: false,
keyDropdownOpen: false,
colorScheme: "light" as "light" | "dark",
})
const initialData = createAsync(() => queryCosts(params.id!, store.year, store.month))
const onPreviousMonth = async () => {
const month = store.month === 0 ? 11 : store.month - 1
const year = store.month === 0 ? store.year - 1 : store.year
const data = await getCosts(params.id!, year, month)
setStore({ month, year, data })
setStore({ month, year })
}
const onNextMonth = async () => {
const month = store.month === 11 ? 0 : store.month + 1
const year = store.month === 11 ? store.year + 1 : store.year
setStore({ month, year, data: await getCosts(params.id!, year, month) })
setStore({ month, year })
}
const onSelectModel = (model: string | null) => setStore({ model, modelDropdownOpen: false })
const onSelectKey = (keyID: string | null) => setStore({ key: keyID, keyDropdownOpen: false })
const getData = createMemo(() => store.data ?? initialData())
const getModels = createMemo(() => {
const data = getData()
if (!data?.usage) return []
return Array.from(new Set(data.usage.map((row) => row.model))).sort()
if (!store.data?.usage) return []
return Array.from(new Set(store.data.usage.map((row) => row.model))).sort()
})
const getDates = createMemo(() => {
@@ -200,22 +199,29 @@ export function GraphSection() {
const isCurrentMonth = () => store.year === now.getFullYear() && store.month === now.getMonth()
const chartConfig = createMemo((): ChartConfiguration | null => {
const data = getData()
const data = store.data
const dates = getDates()
if (!data?.usage?.length) return null
const filteredUsageResults = store.key ? data.usage.filter((row) => row.keyId === store.key) : data.usage
store.colorScheme
const styles = getComputedStyle(document.documentElement)
const colorTextMuted = styles.getPropertyValue("--color-text-muted").trim()
const colorBorderMuted = styles.getPropertyValue("--color-border-muted").trim()
const colorBgElevated = styles.getPropertyValue("--color-bg-elevated").trim()
const colorText = styles.getPropertyValue("--color-text").trim()
const colorTextSecondary = styles.getPropertyValue("--color-text-secondary").trim()
const colorBorder = styles.getPropertyValue("--color-border").trim()
const dailyData = new Map<string, Map<string, number>>()
for (const dateKey of dates) dailyData.set(dateKey, new Map())
for (const row of filteredUsageResults) {
const dayMap = dailyData.get(row.date)
if (dayMap) {
const existing = dayMap.get(row.model) || 0
dayMap.set(row.model, existing + row.totalCost)
}
}
data.usage
.filter((row) => (store.key ? row.keyId === store.key : true))
.forEach((row) => {
const dayMap = dailyData.get(row.date)
if (!dayMap) return
dayMap.set(row.model, (dayMap.get(row.model) ?? 0) + row.totalCost)
})
const filteredModels = store.model === null ? getModels() : [store.model]
@@ -223,7 +229,7 @@ export function GraphSection() {
const color = getModelColor(model)
return {
label: model,
data: dates.map((date) => (dailyData.get(date)?.get(model) || 0) / 100000000),
data: dates.map((date) => (dailyData.get(date)?.get(model) || 0) / 100_000_000),
backgroundColor: color,
hoverBackgroundColor: color,
borderWidth: 0,
@@ -248,7 +254,7 @@ export function GraphSection() {
ticks: {
maxRotation: 0,
autoSkipPadding: 20,
color: "rgba(255, 255, 255, 0.5)",
color: colorTextMuted,
font: {
family: "monospace",
size: 11,
@@ -259,10 +265,10 @@ export function GraphSection() {
stacked: true,
beginAtZero: true,
grid: {
color: "rgba(255, 255, 255, 0.1)",
color: colorBorderMuted,
},
ticks: {
color: "rgba(255, 255, 255, 0.5)",
color: colorTextMuted,
font: {
family: "monospace",
size: 11,
@@ -278,10 +284,10 @@ export function GraphSection() {
tooltip: {
mode: "index",
intersect: false,
backgroundColor: "rgba(0, 0, 0, 0.9)",
titleColor: "rgba(255, 255, 255, 0.9)",
bodyColor: "rgba(255, 255, 255, 0.8)",
borderColor: "rgba(255, 255, 255, 0.1)",
backgroundColor: colorBgElevated,
titleColor: colorText,
bodyColor: colorTextSecondary,
borderColor: colorBorder,
borderWidth: 1,
padding: 12,
displayColors: true,
@@ -297,7 +303,7 @@ export function GraphSection() {
display: true,
position: "bottom",
labels: {
color: "rgba(255, 255, 255, 0.7)",
color: colorTextSecondary,
font: {
size: 12,
},
@@ -335,15 +341,32 @@ export function GraphSection() {
}
})
createEffect(async () => {
const data = await getCosts(params.id!, store.year, store.month)
setStore({ data })
})
createEffect(() => {
const config = chartConfig()
if (!config || !canvasRef) return
if (chartInstance) chartInstance.destroy()
chartInstance = new Chart(canvasRef, config)
onCleanup(() => chartInstance?.destroy())
})
onCleanup(() => chartInstance?.destroy())
createEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
setStore({ colorScheme: mediaQuery.matches ? "dark" : "light" })
const handleColorSchemeChange = (e: MediaQueryListEvent) => {
setStore({ colorScheme: e.matches ? "dark" : "light" })
}
mediaQuery.addEventListener("change", handleColorSchemeChange)
onCleanup(() => mediaQuery.removeEventListener("change", handleColorSchemeChange))
})
return (
<section class={styles.root}>
@@ -352,55 +375,53 @@ export function GraphSection() {
<p>Usage costs broken down by model.</p>
</div>
<Show when={getData()}>
<div data-slot="filter-container">
<div data-slot="month-picker">
<button data-slot="month-button" onClick={onPreviousMonth}>
<IconChevronLeft />
</button>
<span data-slot="month-label">{formatMonthYear()}</span>
<button data-slot="month-button" onClick={onNextMonth} disabled={isCurrentMonth()}>
<IconChevronRight />
</button>
</div>
<Dropdown
trigger={store.model === null ? "All Models" : store.model}
open={store.modelDropdownOpen}
onOpenChange={(open) => setStore({ modelDropdownOpen: open })}
>
<>
<button data-slot="model-item" onClick={() => onSelectModel(null)}>
<span>All Models</span>
</button>
<For each={getModels()}>
{(model) => (
<button data-slot="model-item" onClick={() => onSelectModel(model)}>
<span>{model}</span>
</button>
)}
</For>
</>
</Dropdown>
<Dropdown
trigger={getKeyName(store.key)}
open={store.keyDropdownOpen}
onOpenChange={(open) => setStore({ keyDropdownOpen: open })}
>
<>
<button data-slot="model-item" onClick={() => onSelectKey(null)}>
<span>All Keys</span>
</button>
<For each={getData()?.keys || []}>
{(key) => (
<button data-slot="model-item" onClick={() => onSelectKey(key.id)}>
<span>{key.displayName}</span>
</button>
)}
</For>
</>
</Dropdown>
<div data-slot="filter-container">
<div data-slot="month-picker">
<button data-slot="month-button" onClick={onPreviousMonth}>
<IconChevronLeft />
</button>
<span data-slot="month-label">{formatMonthYear()}</span>
<button data-slot="month-button" onClick={onNextMonth} disabled={isCurrentMonth()}>
<IconChevronRight />
</button>
</div>
</Show>
<Dropdown
trigger={store.model === null ? "All Models" : store.model}
open={store.modelDropdownOpen}
onOpenChange={(open) => setStore({ modelDropdownOpen: open })}
>
<>
<button data-slot="model-item" onClick={() => onSelectModel(null)}>
<span>All Models</span>
</button>
<For each={getModels()}>
{(model) => (
<button data-slot="model-item" onClick={() => onSelectModel(model)}>
<span>{model}</span>
</button>
)}
</For>
</>
</Dropdown>
<Dropdown
trigger={getKeyName(store.key)}
open={store.keyDropdownOpen}
onOpenChange={(open) => setStore({ keyDropdownOpen: open })}
>
<>
<button data-slot="model-item" onClick={() => onSelectKey(null)}>
<span>All Keys</span>
</button>
<For each={store.data?.keys || []}>
{(key) => (
<button data-slot="model-item" onClick={() => onSelectKey(key.id)}>
<span>{key.displayName}</span>
</button>
)}
</For>
</>
</Dropdown>
</div>
<Show
when={chartConfig()}

View File

@@ -5,11 +5,21 @@ import { withActor } from "~/context/auth.withActor"
import { ZenData } from "@opencode-ai/console-core/model.js"
import styles from "./model-section.module.css"
import { querySessionInfo } from "../common"
import { IconAlibaba, IconAnthropic, IconMoonshotAI, IconOpenAI, IconStealth, IconXai, IconZai } from "~/component/icon"
import {
IconAlibaba,
IconAnthropic,
IconGemini,
IconMoonshotAI,
IconOpenAI,
IconStealth,
IconXai,
IconZai,
} from "~/component/icon"
const getModelLab = (modelId: string) => {
if (modelId.startsWith("claude")) return "Anthropic"
if (modelId.startsWith("gpt")) return "OpenAI"
if (modelId.startsWith("gemini")) return "Google"
if (modelId.startsWith("kimi")) return "Moonshot AI"
if (modelId.startsWith("glm")) return "Z.ai"
if (modelId.startsWith("qwen")) return "Alibaba"
@@ -24,7 +34,17 @@ const getModelsInfo = query(async (workspaceID: string) => {
all: Object.entries(ZenData.list().models)
.filter(([id, _model]) => !["claude-3-5-haiku"].includes(id))
.filter(([id, _model]) => !id.startsWith("alpha-"))
.sort(([_idA, modelA], [_idB, modelB]) => modelA.name.localeCompare(modelB.name))
.sort(([idA, modelA], [idB, modelB]) => {
const priority = ["big-pickle", "grok", "claude", "gpt", "gemini"]
const getPriority = (id: string) => {
const index = priority.findIndex((p) => id.startsWith(p))
return index === -1 ? Infinity : index
}
const pA = getPriority(idA)
const pB = getPriority(idB)
if (pA !== pB) return pA - pB
return modelA.name.localeCompare(modelB.name)
})
.map(([id, model]) => ({ id, name: model.name })),
disabled: await Model.listDisabled(),
}
@@ -96,6 +116,8 @@ export function ModelSection() {
return <IconOpenAI width={16} height={16} />
case "Anthropic":
return <IconAnthropic width={16} height={16} />
case "Google":
return <IconGemini width={16} height={16} />
case "Moonshot AI":
return <IconMoonshotAI width={16} height={16} />
case "Z.ai":

View File

@@ -8,6 +8,7 @@ import styles from "./provider-section.module.css"
const PROVIDERS = [
{ name: "OpenAI", key: "openai", prefix: "sk-" },
{ name: "Anthropic", key: "anthropic", prefix: "sk-ant-" },
{ name: "Google Gemini", key: "google", prefix: "AI" },
] as const
type Provider = (typeof PROVIDERS)[number]

View File

@@ -56,6 +56,53 @@
color: var(--color-text);
font-weight: 500;
}
[data-slot="tokens-with-breakdown"] {
position: relative;
display: flex;
align-items: center;
gap: var(--space-2);
}
[data-slot="breakdown-button"] {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
background: transparent;
border: none;
color: var(--color-text-muted);
cursor: pointer;
transition: color 0.15s ease;
&:hover {
color: var(--color-text);
}
svg {
width: 16px;
height: 16px;
}
}
[data-slot="breakdown-popup"] {
position: absolute;
left: 0;
top: 100%;
margin-top: var(--space-2);
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
padding: var(--space-2);
z-index: 10;
min-width: 180px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
font-size: var(--font-size-xs);
@media (prefers-color-scheme: dark) {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
}
}
tbody tr:last-child td {
@@ -116,4 +163,24 @@
}
}
}
/* Breakdown popup content */
[data-slot="breakdown-row"] {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--space-4);
padding: var(--space-1) 0;
}
[data-slot="breakdown-label"] {
color: var(--color-text-muted);
font-size: var(--font-size-xs);
}
[data-slot="breakdown-value"] {
color: var(--color-text);
font-weight: 500;
font-size: var(--font-size-xs);
}
}

View File

@@ -1,9 +1,9 @@
import { Billing } from "@opencode-ai/console-core/billing.js"
import { createAsync, query, useParams } from "@solidjs/router"
import { createMemo, For, Show, createEffect } from "solid-js"
import { createMemo, For, Show, createEffect, createSignal } from "solid-js"
import { formatDateUTC, formatDateForTable } from "../common"
import { withActor } from "~/context/auth.withActor"
import { IconChevronLeft, IconChevronRight } from "~/component/icon"
import { IconChevronLeft, IconChevronRight, IconBreakdown } from "~/component/icon"
import styles from "./usage-section.module.css"
import { createStore } from "solid-js/store"
@@ -22,15 +22,38 @@ export function UsageSection() {
const params = useParams()
const usage = createAsync(() => queryUsageInfo(params.id!, 0))
const [store, setStore] = createStore({ page: 0, usage: [] as Awaited<ReturnType<typeof getUsageInfo>> })
const [openBreakdownId, setOpenBreakdownId] = createSignal<string | null>(null)
createEffect(() => {
setStore({ usage: usage() })
}, [usage])
createEffect(() => {
if (!openBreakdownId()) return
const handleClickOutside = (e: MouseEvent) => {
const target = e.target as HTMLElement
if (!target.closest('[data-slot="tokens-with-breakdown"]')) {
setOpenBreakdownId(null)
}
}
document.addEventListener("click", handleClickOutside)
return () => document.removeEventListener("click", handleClickOutside)
})
const hasResults = createMemo(() => store.usage && store.usage.length > 0)
const canGoPrev = createMemo(() => store.page > 0)
const canGoNext = createMemo(() => store.usage && store.usage.length === PAGE_SIZE)
const calculateTotalInputTokens = (u: Awaited<ReturnType<typeof getUsageInfo>>[0]) => {
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWrite5mTokens ?? 0) + (u.cacheWrite1hTokens ?? 0)
}
const calculateTotalOutputTokens = (u: Awaited<ReturnType<typeof getUsageInfo>>[0]) => {
return u.outputTokens + (u.reasoningTokens ?? 0)
}
const goPrev = async () => {
const usage = await getUsageInfo(params.id!, store.page - 1)
setStore({
@@ -73,16 +96,79 @@ export function UsageSection() {
</thead>
<tbody>
<For each={store.usage}>
{(usage) => {
{(usage, index) => {
const date = createMemo(() => new Date(usage.timeCreated))
const totalInputTokens = createMemo(() => calculateTotalInputTokens(usage))
const totalOutputTokens = createMemo(() => calculateTotalOutputTokens(usage))
const inputBreakdownId = `input-breakdown-${index()}`
const outputBreakdownId = `output-breakdown-${index()}`
const isInputOpen = createMemo(() => openBreakdownId() === inputBreakdownId)
const isOutputOpen = createMemo(() => openBreakdownId() === outputBreakdownId)
const isClaude = usage.model.toLowerCase().includes("claude")
return (
<tr>
<td data-slot="usage-date" title={formatDateUTC(date())}>
{formatDateForTable(date())}
</td>
<td data-slot="usage-model">{usage.model}</td>
<td data-slot="usage-tokens">{usage.inputTokens}</td>
<td data-slot="usage-tokens">{usage.outputTokens}</td>
<td data-slot="usage-tokens">
<div data-slot="tokens-with-breakdown" onClick={(e) => e.stopPropagation()}>
<button
data-slot="breakdown-button"
onClick={(e) => {
e.stopPropagation()
setOpenBreakdownId(isInputOpen() ? null : inputBreakdownId)
}}
>
<IconBreakdown />
</button>
<span onClick={() => setOpenBreakdownId(null)}>{totalInputTokens()}</span>
<Show when={isInputOpen()}>
<div data-slot="breakdown-popup" onClick={(e) => e.stopPropagation()}>
<div data-slot="breakdown-row">
<span data-slot="breakdown-label">Input</span>
<span data-slot="breakdown-value">{usage.inputTokens}</span>
</div>
<div data-slot="breakdown-row">
<span data-slot="breakdown-label">Cache Read</span>
<span data-slot="breakdown-value">{usage.cacheReadTokens ?? 0}</span>
</div>
<Show when={isClaude}>
<div data-slot="breakdown-row">
<span data-slot="breakdown-label">Cache Write</span>
<span data-slot="breakdown-value">{usage.cacheWrite5mTokens ?? 0}</span>
</div>
</Show>
</div>
</Show>
</div>
</td>
<td data-slot="usage-tokens">
<div data-slot="tokens-with-breakdown" onClick={(e) => e.stopPropagation()}>
<button
data-slot="breakdown-button"
onClick={(e) => {
e.stopPropagation()
setOpenBreakdownId(isOutputOpen() ? null : outputBreakdownId)
}}
>
<IconBreakdown />
</button>
<span onClick={() => setOpenBreakdownId(null)}>{totalOutputTokens()}</span>
<Show when={isOutputOpen()}>
<div data-slot="breakdown-popup" onClick={(e) => e.stopPropagation()}>
<div data-slot="breakdown-row">
<span data-slot="breakdown-label">Output</span>
<span data-slot="breakdown-value">{usage.outputTokens}</span>
</div>
<div data-slot="breakdown-row">
<span data-slot="breakdown-label">Reasoning</span>
<span data-slot="breakdown-value">{usage.reasoningTokens ?? 0}</span>
</div>
</div>
</Show>
</div>
</td>
<td data-slot="usage-cost">${((usage.cost ?? 0) / 100000000).toFixed(4)}</td>
</tr>
)

View File

@@ -1,7 +1,7 @@
import "./index.css"
import { createAsync, query, redirect } from "@solidjs/router"
import { Title, Meta, Link } from "@solidjs/meta"
import { HttpHeader } from "@solidjs/start"
// import { HttpHeader } from "@solidjs/start"
import zenLogoLight from "../../asset/zen-ornate-light.svg"
import { config } from "~/config"
import zenLogoDark from "../../asset/zen-ornate-dark.svg"
@@ -18,23 +18,24 @@ import { Legal } from "~/component/legal"
import { Footer } from "~/component/footer"
import { Header } from "~/component/header"
import { getLastSeenWorkspaceID } from "../workspace/common"
import { IconGemini, IconZai } from "~/component/icon"
const checkLoggedIn = query(async () => {
"use server"
const workspaceID = await getLastSeenWorkspaceID()
const workspaceID = await getLastSeenWorkspaceID().catch(() => {})
if (workspaceID) throw redirect(`/workspace/${workspaceID}`)
}, "checkLoggedIn.get")
export default function Home() {
createAsync(() => checkLoggedIn())
const loggedin = createAsync(() => checkLoggedIn())
return (
<main data-page="zen">
<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />
{/*<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />*/}
<Title>OpenCode Zen | A curated set of reliable optimized models for coding agents</Title>
<Link rel="canonical" href={`${config.baseUrl}/zen`} />
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
<Meta property="og:image" content="/social-share-zen.png" />
<Meta name="twitter:image" content="/social-share-zen.png" />
<Meta name="opencode:auth" content={loggedin() ? "true" : "false"} />
<div data-component="container">
<Header zen />
@@ -81,6 +82,9 @@ export default function Home() {
/>
</svg>
</div>
<div>
<IconGemini width="24" height="24" />
</div>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
@@ -111,6 +115,9 @@ export default function Home() {
/>
</svg>
</div>
<div>
<IconZai width="24" height="24" />
</div>
</div>
<a href="/auth">
<span>Get started with Zen </span>

View File

@@ -0,0 +1,38 @@
import { Resource, waitUntil } from "@opencode-ai/console-resource"
export function createDataDumper(sessionId: string, requestId: string, projectId: string) {
if (Resource.App.stage !== "production") return
if (sessionId === "") return
let data: Record<string, any> = { sessionId, requestId, projectId }
let metadata: Record<string, any> = { sessionId, requestId, projectId }
return {
provideModel: (model?: string) => {
data.modelName = model
metadata.modelName = model
},
provideRequest: (request: string) => (data.request = request),
provideResponse: (response: string) => (data.response = response),
provideStream: (chunk: string) => (data.response = (data.response ?? "") + chunk),
flush: () => {
if (!data.modelName) return
const timestamp = new Date().toISOString().replace(/[^0-9]/g, "")
waitUntil(
Resource.ZenData.put(
`data/${data.modelName}/${sessionId}/${requestId}.json`,
JSON.stringify({ timestamp, ...data }),
),
)
waitUntil(
Resource.ZenData.put(
`meta/${data.modelName}/${timestamp}/${requestId}.json`,
JSON.stringify({ timestamp, ...metadata }),
),
)
},
}
}

View File

@@ -13,11 +13,15 @@ import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
import { logger } from "./logger"
import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError, RateLimitError } from "./error"
import { createBodyConverter, createStreamPartConverter, createResponseConverter } from "./provider/provider"
import { createBodyConverter, createStreamPartConverter, createResponseConverter, UsageInfo } from "./provider/provider"
import { anthropicHelper } from "./provider/anthropic"
import { googleHelper } from "./provider/google"
import { openaiHelper } from "./provider/openai"
import { oaCompatHelper } from "./provider/openai-compatible"
import { createRateLimiter } from "./rateLimiter"
import { createDataDumper } from "./dataDumper"
import { createTrialLimiter } from "./trialLimiter"
import { createStickyTracker } from "./stickyProviderTracker"
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
type RetryOptions = {
@@ -30,6 +34,8 @@ export async function handler(
opts: {
format: ZenData.Format
parseApiKey: (headers: Headers) => string | undefined
parseModel: (url: string, body: any) => string
parseIsStream: (url: string, body: any) => boolean
},
) {
type AuthInfo = Awaited<ReturnType<typeof authenticate>>
@@ -43,28 +49,47 @@ export async function handler(
]
try {
const url = input.request.url
const body = await input.request.json()
const model = opts.parseModel(url, body)
const isStream = opts.parseIsStream(url, body)
const ip = input.request.headers.get("x-real-ip") ?? ""
const sessionId = input.request.headers.get("x-opencode-session") ?? ""
const requestId = input.request.headers.get("x-opencode-request") ?? ""
const projectId = input.request.headers.get("x-opencode-project") ?? ""
logger.metric({
is_tream: !!body.stream,
session: input.request.headers.get("x-opencode-session"),
request: input.request.headers.get("x-opencode-request"),
is_tream: isStream,
session: sessionId,
request: requestId,
})
const zenData = ZenData.list()
const modelInfo = validateModel(zenData, body.model)
const modelInfo = validateModel(zenData, model)
const dataDumper = createDataDumper(sessionId, requestId, projectId)
const trialLimiter = createTrialLimiter(modelInfo.trial?.limit, ip)
const isTrial = await trialLimiter?.isTrial()
const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip)
await rateLimiter?.check()
const stickyTracker = createStickyTracker(modelInfo.stickyProvider ?? false, sessionId)
const stickyProvider = await stickyTracker?.get()
const retriableRequest = async (retry: RetryOptions = { excludeProviders: [], retryCount: 0 }) => {
const providerInfo = selectProvider(zenData, modelInfo, ip, retry)
const authInfo = await authenticate(modelInfo, providerInfo)
const authInfo = await authenticate(modelInfo)
const providerInfo = selectProvider(
zenData,
authInfo,
modelInfo,
sessionId,
isTrial ?? false,
retry,
stickyProvider,
)
validateBilling(authInfo, modelInfo)
validateModelSettings(authInfo)
updateProviderKey(authInfo, providerInfo)
logger.metric({ provider: providerInfo.id })
const startTimestamp = Date.now()
const reqUrl = providerInfo.modifyUrl(providerInfo.api)
const reqUrl = providerInfo.modifyUrl(providerInfo.api, providerInfo.model, isStream)
const reqBody = JSON.stringify(
providerInfo.modifyBody({
...createBodyConverter(opts.format, providerInfo.format)(body),
@@ -98,10 +123,17 @@ export async function handler(
})
}
return { providerInfo, authInfo, res, startTimestamp }
return { providerInfo, authInfo, reqBody, res, startTimestamp }
}
const { providerInfo, authInfo, res, startTimestamp } = await retriableRequest()
const { providerInfo, authInfo, reqBody, res, startTimestamp } = await retriableRequest()
// Store model request
dataDumper?.provideModel(providerInfo.storeModel)
dataDumper?.provideRequest(reqBody)
// Store sticky provider
await stickyTracker?.set(providerInfo.id)
// Scrub response headers
const resHeaders = new Headers()
@@ -114,14 +146,18 @@ export async function handler(
logger.debug("STATUS: " + res.status + " " + res.statusText)
// Handle non-streaming response
if (!body.stream) {
if (!isStream) {
const responseConverter = createResponseConverter(providerInfo.format, opts.format)
const json = await res.json()
const body = JSON.stringify(responseConverter(json))
logger.metric({ response_length: body.length })
logger.debug("RESPONSE: " + body)
dataDumper?.provideResponse(body)
dataDumper?.flush()
const tokensInfo = providerInfo.normalizeUsage(json.usage)
await trialLimiter?.track(tokensInfo)
await rateLimiter?.track()
await trackUsage(authInfo, modelInfo, providerInfo, json.usage)
await trackUsage(authInfo, modelInfo, providerInfo, tokensInfo)
await reload(authInfo)
return new Response(body, {
status: res.status,
@@ -149,10 +185,13 @@ export async function handler(
response_length: responseLength,
"timestamp.last_byte": Date.now(),
})
dataDumper?.flush()
await rateLimiter?.track()
const usage = usageParser.retrieve()
if (usage) {
await trackUsage(authInfo, modelInfo, providerInfo, usage)
const tokensInfo = providerInfo.normalizeUsage(usage)
await trialLimiter?.track(tokensInfo)
await trackUsage(authInfo, modelInfo, providerInfo, tokensInfo)
await reload(authInfo)
}
c.close()
@@ -168,8 +207,9 @@ export async function handler(
}
responseLength += value.length
buffer += decoder.decode(value, { stream: true })
dataDumper?.provideStream(buffer)
const parts = buffer.split("\n\n")
const parts = buffer.split(providerInfo.streamSeparator)
buffer = parts.pop() ?? ""
for (let part of parts) {
@@ -257,8 +297,29 @@ export async function handler(
return { id: modelId, ...modelData }
}
function selectProvider(zenData: ZenData, modelInfo: ModelInfo, ip: string, retry: RetryOptions) {
function selectProvider(
zenData: ZenData,
authInfo: AuthInfo,
modelInfo: ModelInfo,
sessionId: string,
isTrial: boolean,
retry: RetryOptions,
stickyProvider: string | undefined,
) {
const provider = (() => {
if (authInfo?.provider?.credentials) {
return modelInfo.providers.find((provider) => provider.id === modelInfo.byokProvider)
}
if (isTrial) {
return modelInfo.providers.find((provider) => provider.id === modelInfo.trial!.provider)
}
if (stickyProvider) {
const provider = modelInfo.providers.find((provider) => provider.id === stickyProvider)
if (provider) return provider
}
if (retry.retryCount === MAX_RETRIES) {
return modelInfo.providers.find((provider) => provider.id === modelInfo.fallbackProvider)
}
@@ -268,9 +329,13 @@ export async function handler(
.filter((provider) => !retry.excludeProviders.includes(provider.id))
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
// Use the last 2 characters of IP address to select a provider
const lastChars = ip.slice(-2)
const index = parseInt(lastChars, 16) % providers.length
// Use the last 4 characters of session ID to select a provider
let h = 0
const l = sessionId.length
for (let i = l - 4; i < l; i++) {
h = (h * 31 + sessionId.charCodeAt(i)) | 0 // 32-bit int
}
const index = (h >>> 0) % providers.length // make unsigned + range 0..length-1
return providers[index || 0]
})()
@@ -283,13 +348,14 @@ export async function handler(
...(() => {
const format = zenData.providers[provider.id].format
if (format === "anthropic") return anthropicHelper
if (format === "google") return googleHelper
if (format === "openai") return openaiHelper
return oaCompatHelper
})(),
}
}
async function authenticate(modelInfo: ModelInfo, providerInfo: ProviderInfo) {
async function authenticate(modelInfo: ModelInfo) {
const apiKey = opts.parseApiKey(input.request.headers)
if (!apiKey || apiKey === "public") {
if (modelInfo.allowAnonymous) return
@@ -327,7 +393,12 @@ export async function handler(
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, modelInfo.id)))
.leftJoin(
ProviderTable,
and(eq(ProviderTable.workspaceID, KeyTable.workspaceID), eq(ProviderTable.provider, providerInfo.id)),
modelInfo.byokProvider
? and(
eq(ProviderTable.workspaceID, KeyTable.workspaceID),
eq(ProviderTable.provider, modelInfo.byokProvider),
)
: sql`false`,
)
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
.then((rows) => rows[0]),
@@ -404,14 +475,18 @@ export async function handler(
}
function updateProviderKey(authInfo: AuthInfo, providerInfo: ProviderInfo) {
if (!authInfo) return
if (!authInfo.provider?.credentials) return
if (!authInfo?.provider?.credentials) return
providerInfo.apiKey = authInfo.provider.credentials
}
async function trackUsage(authInfo: AuthInfo, modelInfo: ModelInfo, providerInfo: ProviderInfo, usage: any) {
async function trackUsage(
authInfo: AuthInfo,
modelInfo: ModelInfo,
providerInfo: ProviderInfo,
usageInfo: UsageInfo,
) {
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
providerInfo.normalizeUsage(usage)
usageInfo
const modelCost =
modelInfo.cost200K &&

View File

@@ -30,6 +30,7 @@ export const anthropicHelper = {
service_tier: "standard_only",
}
},
streamSeparator: "\n\n",
createUsageParser: () => {
let usage: Usage

View File

@@ -0,0 +1,74 @@
import { ProviderHelper } from "./provider"
/*
{
promptTokenCount: 11453,
candidatesTokenCount: 71,
totalTokenCount: 11625,
cachedContentTokenCount: 8100,
promptTokensDetails: [
{modality: "TEXT",tokenCount: 11453}
],
cacheTokensDetails: [
{modality: "TEXT",tokenCount: 8100}
],
thoughtsTokenCount: 101
}
*/
type Usage = {
promptTokenCount?: number
candidatesTokenCount?: number
totalTokenCount?: number
cachedContentTokenCount?: number
promptTokensDetails?: { modality: string; tokenCount: number }[]
cacheTokensDetails?: { modality: string; tokenCount: number }[]
thoughtsTokenCount?: number
}
export const googleHelper = {
format: "google",
modifyUrl: (providerApi: string, model?: string, isStream?: boolean) =>
`${providerApi}/models/${model}:${isStream ? "streamGenerateContent?alt=sse" : "generateContent"}`,
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
headers.set("x-goog-api-key", apiKey)
},
modifyBody: (body: Record<string, any>) => {
return body
},
streamSeparator: "\r\n\r\n",
createUsageParser: () => {
let usage: Usage
return {
parse: (chunk: string) => {
if (!chunk.startsWith("data: ")) return
let json
try {
json = JSON.parse(chunk.slice(6)) as { usageMetadata?: Usage }
} catch (e) {
return
}
if (!json.usageMetadata) return
usage = json.usageMetadata
},
retrieve: () => usage,
}
},
normalizeUsage: (usage: Usage) => {
const inputTokens = usage.promptTokenCount ?? 0
const outputTokens = usage.candidatesTokenCount ?? 0
const reasoningTokens = usage.thoughtsTokenCount ?? 0
const cacheReadTokens = usage.cachedContentTokenCount ?? 0
return {
inputTokens: inputTokens - cacheReadTokens,
outputTokens,
reasoningTokens,
cacheReadTokens,
cacheWrite5mTokens: undefined,
cacheWrite1hTokens: undefined,
}
},
} satisfies ProviderHelper

View File

@@ -33,6 +33,7 @@ export const oaCompatHelper = {
...(body.stream ? { stream_options: { include_usage: true } } : {}),
}
},
streamSeparator: "\n\n",
createUsageParser: () => {
let usage: Usage

View File

@@ -21,6 +21,7 @@ export const openaiHelper = {
modifyBody: (body: Record<string, any>) => {
return body
},
streamSeparator: "\n\n",
createUsageParser: () => {
let usage: Usage

View File

@@ -24,23 +24,26 @@ import {
toOaCompatibleResponse,
} from "./openai-compatible"
export type UsageInfo = {
inputTokens: number
outputTokens: number
reasoningTokens?: number
cacheReadTokens?: number
cacheWrite5mTokens?: number
cacheWrite1hTokens?: number
}
export type ProviderHelper = {
format: ZenData.Format
modifyUrl: (providerApi: string) => string
modifyUrl: (providerApi: string, model?: string, isStream?: boolean) => string
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => void
modifyBody: (body: Record<string, any>) => Record<string, any>
streamSeparator: string
createUsageParser: () => {
parse: (chunk: string) => void
retrieve: () => any
}
normalizeUsage: (usage: any) => {
inputTokens: number
outputTokens: number
reasoningTokens?: number
cacheReadTokens?: number
cacheWrite5mTokens?: number
cacheWrite1hTokens?: number
}
normalizeUsage: (usage: any) => UsageInfo
}
export interface CommonMessage {

View File

@@ -0,0 +1,16 @@
import { Resource } from "@opencode-ai/console-resource"
export function createStickyTracker(stickyProvider: boolean, session: string) {
if (!stickyProvider) return
if (!session) return
const key = `sticky:${session}`
return {
get: async () => {
return await Resource.GatewayKv.get(key)
},
set: async (providerId: string) => {
await Resource.GatewayKv.put(key, providerId, { expirationTtl: 86400 })
},
}
}

View File

@@ -0,0 +1,43 @@
import { Database, eq, sql } from "@opencode-ai/console-core/drizzle/index.js"
import { IpTable } from "@opencode-ai/console-core/schema/ip.sql.js"
import { UsageInfo } from "./provider/provider"
export function createTrialLimiter(limit: number | undefined, ip: string) {
if (!limit) return
if (!ip) return
let trial: boolean
return {
isTrial: async () => {
const data = await Database.use((tx) =>
tx
.select({
usage: IpTable.usage,
})
.from(IpTable)
.where(eq(IpTable.ip, ip))
.then((rows) => rows[0]),
)
trial = (data?.usage ?? 0) < limit
return trial
},
track: async (usageInfo: UsageInfo) => {
if (!trial) return
const usage =
usageInfo.inputTokens +
usageInfo.outputTokens +
(usageInfo.reasoningTokens ?? 0) +
(usageInfo.cacheReadTokens ?? 0) +
(usageInfo.cacheWrite5mTokens ?? 0) +
(usageInfo.cacheWrite1hTokens ?? 0)
await Database.use((tx) =>
tx
.insert(IpTable)
.values({ ip, usage })
.onDuplicateKeyUpdate({ set: { usage: sql`${IpTable.usage} + ${usage}` } }),
)
},
}
}

View File

@@ -5,5 +5,7 @@ export function POST(input: APIEvent) {
return handler(input, {
format: "oa-compat",
parseApiKey: (headers: Headers) => headers.get("authorization")?.split(" ")[1],
parseModel: (url: string, body: any) => body.model,
parseIsStream: (url: string, body: any) => !!body.stream,
})
}

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