Compare commits

..
673 Commits
Author SHA1 Message Date
opencode 6ac5a447c2 release: v0.15.12 2025-10-21 17:31:56 +00:00
Aiden Cline cb4670e6de ignore: add label 2025-10-21 11:12:52 -05:00
Aiden ClineandGitHub ca0f3902b7 fix: provider option transforms (#3331) 2025-10-21 11:08:21 -05:00
Dax Raad e9996342a7 core: provide line-level statistics in file diffs to help users understand the scale of changes 2025-10-21 11:54:41 -04:00
opencode a84826061d release: v0.15.11 2025-10-21 15:04:22 +00:00
Dax Raad 7a20f77ebf core: improve error handling with console output for debugging 2025-10-21 10:55:10 -04:00
Giuseppe RotaandGitHub 731122bf99 fix(acp): use newer acp package (#3317) 2025-10-21 09:35:09 -05:00
GitHub Action f9036734eb ignore: update download stats 2025-10-21 2025-10-21 12:06:20 +00:00
kcrommettandGitHub a99bd3aa2c tweak: adjust file api to encode images (#3292) 2025-10-21 00:52:39 -05:00
zWingandGitHub 96efede846 fix: openai options when using @ai-sdk/azure (#3315) 2025-10-20 23:30:13 -05:00
Cheol KangGitHubopencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>rekram1-nodeAiden Cline
2f66055d25 feat: add -f/--file flag to opencode run command (#3295)
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-10-20 23:25:54 -05:00
opencode 6995dab1dc release: v0.15.10 2025-10-20 22:21:03 +00:00
Dax Raad a0a09f421c core: add session diff API to show file changes between snapshots 2025-10-20 17:59:26 -04:00
f3f21194ae feat: Add ACP (Agent Client Protocol) support (#2947)
Co-authored-by: opencode-bot <devnull@opencode.local>
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: GitHub Action <action@github.com>
2025-10-20 16:55:22 -05:00
opencode 835fa9fb81 release: v0.15.9 2025-10-20 21:16:57 +00:00
Aiden Cline 96ae6d51aa ignore: link labels 2025-10-20 16:02:23 -05:00
Frank 075ef0fa34 wip: share 2025-10-20 16:17:51 -04:00
Aiden ClineandGitHub 89b72e4442 fix: bash tool permission merges (#3302) 2025-10-20 15:15:14 -05:00
Frank 7a7b3c6315 wip: zen 2025-10-20 13:22:43 -04:00
Rui FerrãoandGitHub 3d48c14d29 docs: clarify the effects of the subtask command option with primary … (#3299) 2025-10-20 12:16:09 -05:00
GitHub Action bfa79ed44b ignore: update download stats 2025-10-20 2025-10-20 12:04:59 +00:00
Hieu NguyenandGitHub 4d8268c818 feat: support astro lsp (#3242) 2025-10-19 22:49:06 -05:00
SquibidandGitHub 95d413bec6 theme: add mellow theme (#3198) 2025-10-19 22:34:04 -05:00
Joscha GötzerandGitHub 1cb5a70382 feat(theme): Add Night Owl theme (#3269) 2025-10-19 22:30:04 -05:00
WalterandGitHub 6adc16ca8a fix(tui): Allow modals to handle ESC key before force closing (#3279) 2025-10-19 22:16:54 -05:00
ZeldrisandGitHub 10ebe9ae09 docs: add scoop & winget to readme (#3215) 2025-10-19 21:50:51 -05:00
Aiden Cline 43a07c6aca hide invalid option 2025-10-19 20:51:33 -05:00
Aiden ClineandGitHub 5d3a88f34f fix: snapshot undo bug (#3290) 2025-10-19 18:42:34 -05:00
Ivan UhalinandGitHub e47edfffe4 docs: fix Grep by Vercel link in documentation (#3280) 2025-10-19 11:51:57 -05:00
GitHub Action 141097fc73 ignore: update download stats 2025-10-19 2025-10-19 12:04:24 +00:00
Aiden Cline c8898463a7 ignore: adjust template 2025-10-18 23:45:01 -05:00
Aiden ClineandGitHub 1c7bd6365e replace all $ARGUMENTS (#3276) 2025-10-18 23:37:17 -05:00
Aiden Cline 290d15a80f ignore: add version to bug template 2025-10-18 14:56:06 -05:00
233a018fe5 docs: contributing.md (#3248)
Co-authored-by: Jay <air@live.ca>
2025-10-18 14:10:14 -05:00
opencode d69beec087 release: v0.15.8 2025-10-18 18:36:52 +00:00
Aiden ClineandGitHub 1f869bccc1 make compact interruptable (#3251) 2025-10-18 11:49:29 -05:00
GitHub Action 8da8c9e78c ignore: update download stats 2025-10-18 2025-10-18 12:04:14 +00:00
Adam 335d833655 wip: desktop work 2025-10-17 15:22:11 -05:00
Haris GušićandGitHub 1dba01e057 Improve typo directory error (#3247) 2025-10-17 14:34:37 -05:00
Jay V a3de43f3de ignore: clarify that workspaces are free for teams during beta 2025-10-17 15:19:19 -04:00
Jay V 22ad4f5365 ignore: help users discover that teams feature is free during beta 2025-10-17 14:33:21 -04:00
Jay V 5bfbec60b5 docs: clarify team collaboration features and pricing 2025-10-17 13:58:10 -04:00
Adam cc18b58ff9 wip: desktop work 2025-10-17 12:07:58 -05:00
Adam 887a819f24 wip: desktop work 2025-10-17 12:06:36 -05:00
mgrachtenandGitHub fe8b3a2515 set 755 permissions (#3237) 2025-10-17 10:42:42 -05:00
GitHub Action 86079353ef ignore: update download stats 2025-10-17 2025-10-17 12:04:43 +00:00
Frank b7c8690414 wip: zen 2025-10-17 02:23:45 -04:00
Frank c25b9bf65a wip: zen 2025-10-17 01:15:25 -04:00
ddb2e6957c added AU inference for bedrock haiku 4.5 (#3206)
Co-authored-by: Matt Gillard <matt-github@gillard.biz>
2025-10-16 23:48:41 -05:00
Frank a590b32a10 wip: zen 2025-10-17 00:26:00 -04:00
Frank 5f7bba11fd wip: zen 2025-10-16 23:43:49 -04:00
Frank 4663ea5faa wip: zen 2025-10-16 23:19:25 -04:00
Frankandopencode dd581e8577 wip: zen 2025-10-17 03:17:07 +00:00
opencode bad01d76de release: v0.15.7 2025-10-17 03:17:07 +00:00
Aiden Cline d69366b00c Revert "try to avoid persisting empty thinking/text blocks"
This reverts commit d8a15e7bc9.
2025-10-16 22:04:55 -05:00
Frank 1947580b08 wip: zen 2025-10-16 22:28:34 -04:00
Frank ca9b13e8a2 wip: zen 2025-10-16 22:28:09 -04:00
Hieu NguyenGitHubhiunguynxopencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
92d9a0ec61 feat: deno lsp (#3210)
Co-authored-by: hiunguynx <hieu.nm1@teko.vn>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
2025-10-16 18:08:36 -05:00
opencode 2be9ed2590 release: v0.15.6 2025-10-16 23:02:59 +00:00
Aiden Cline 25861f6d0d sync 2025-10-16 17:49:02 -05:00
Aiden ClineandGitHub b24f4e3d2c fix: timeout option (#3229) 2025-10-16 17:47:41 -05:00
Frank 729ad1cb75 wip: zen 2025-10-16 17:50:32 -04:00
Haris GušićandGitHub fb4105a46c docs: fix Ctrl+K styling in documentation (#3021) 2025-10-16 15:30:28 -05:00
Frank 7abc3e9794 ci: fix 2025-10-16 16:04:25 -04:00
Frank 88fef05923 wip: zen 2025-10-16 15:58:51 -04:00
GitHub Action 8552f3555e chore: format code 2025-10-16 19:55:30 +00:00
Adam 47d9e01765 wip: css/ui and desktop work 2025-10-16 14:53:44 -05:00
Aiden ClineandGitHub fc18fc8a08 fix: bash hangs & orphans (#3225) 2025-10-16 14:39:36 -05:00
Dax Raad 7474788778 ci: fix 2025-10-16 15:36:12 -04:00
GitHub Action 26d0d20e4d chore: format code 2025-10-16 19:08:21 +00:00
Adam 20229f147b wip: css/ui and desktop work 2025-10-16 14:07:37 -05:00
Aiden Cline 149cb6a9ec fix: connection closed
publish-github-action / publish (push) Has been cancelled
2025-10-16 14:00:07 -05:00
Frank 7ec5e49e19 zen: support stripe link 2025-10-16 14:59:46 -04:00
Aiden Cline 1c1380d3c8 adjust action
publish-github-action / publish (push) Has been cancelled
2025-10-16 13:15:27 -05:00
Adamandopencode 10680f0cf0 wip: css/ui work 2025-10-16 18:06:59 +00:00
opencode 2517b22552 release: v0.15.5 2025-10-16 18:06:59 +00:00
Aiden Cline 64617c113a ignore: tweak permissions 2025-10-16 12:48:39 -05:00
Aiden ClineandGitHub 860c6338fc fix: github action (#3223) 2025-10-16 12:33:33 -05:00
Aiden Cline 4a7551e87b ci: fix changelog generation 2025-10-16 11:29:58 -05:00
Moisès MaciàandGitHub 285cc4b9fd docs: fix misspelled word (#3211) 2025-10-16 10:04:11 -05:00
Dax Raad d8a15e7bc9 try to avoid persisting empty thinking/text blocks 2025-10-16 10:54:10 -04:00
opencode 542b9fa342 release: v0.15.4 2025-10-16 14:53:32 +00:00
GitHub Action 9159afb54b ignore: update download stats 2025-10-16 2025-10-16 12:04:48 +00:00
seridescentandGitHub 536934548a fix: use ai-sdk openai chat language model instead of completion language model (#3204) 2025-10-16 00:59:49 -05:00
Aiden ClineandGitHub 1c59530115 Revert "fix: Text content blocks must contain non-whitespace text" (#3200) 2025-10-15 20:02:17 -05:00
Dax Raad ab8471a7ff core: filter out alpha status models from provider list 2025-10-15 20:12:37 -04:00
Dax Raad 4c674b075b ci: stuff 2025-10-15 19:59:46 -04:00
Dax Raad ba8a4c5e9f snapshot publish everything 2025-10-15 19:53:14 -04:00
Dax Raad 790fe72f39 sync 2025-10-15 19:48:57 -04:00
Aiden Cline 2d2d4641cb ignore: update readme 2025-10-15 16:06:11 -05:00
Aiden Cline d3caa55c10 Revert "fix: spawns hanging (#3192)"
This reverts commit 278ffb9a4e.
2025-10-15 15:20:14 -05:00
ca534a36e5 feat: make compact feature use streaming API (#3079)
Co-authored-by: fku <fabian.kukuck@ipt.ch>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-10-15 13:44:16 -05:00
Aiden ClineandGitHub 278ffb9a4e fix: spawns hanging (#3192) 2025-10-15 13:01:54 -05:00
Aiden ClineandGitHub b2ff4be4c6 fix: Text content blocks must contain non-whitespace text (#3194) 2025-10-15 13:00:26 -05:00
Frank 2267ce2511 zen: support haiku 4.5 2025-10-15 13:53:00 -04:00
e29d1d339c updated bedrock provider for the new Australian sonnet 4.5 cross region inference (#3050)
Co-authored-by: Matt Gillard <matt-github@gillard.biz>
2025-10-15 11:09:22 -05:00
Haris GušićandGitHub 92bc78a2d3 Improve http error codes (#3186) 2025-10-15 10:53:09 -05:00
GitHub Action 1ba5535460 ignore: update download stats 2025-10-15 2025-10-15 12:04:51 +00:00
Frank 7fa9a73bf0 wip: zen 2025-10-15 02:55:01 -04:00
Aiden ClineandGitHub b3fcc9a81d tweak: consolidate session lock logic (#3185) 2025-10-15 01:12:51 -05:00
Frank e8751d976e wip: zen 2025-10-15 01:07:57 -04:00
Frank 43c9702aa7 wip: zen 2025-10-15 00:02:38 -04:00
Frank ae609be710 wip: zen 2025-10-14 23:45:06 -04:00
Frank 86ee36f562 wip: zen 2025-10-14 23:38:21 -04:00
Frank 0657f09139 wip: zen 2025-10-14 23:04:41 -04:00
Frank 182949dee4 wip: zen 2025-10-14 23:03:13 -04:00
Dax Raad 83655a3b09 ci: run typecheck before tests to catch type errors early 2025-10-14 18:36:03 -04:00
Dax Raad 62e5f4b154 try tsgo 2025-10-14 18:30:32 -04:00
Jay V ea926f0e1a ignore: prompt 2025-10-14 17:45:10 -04:00
Jay V 6191232d5f web: colocate copy button styles with components that use them 2025-10-14 17:41:17 -04:00
Frank 95f4ce86d6 ci: fix 2025-10-14 17:22:29 -04:00
Frank 5999aefde3 wip: zen 2025-10-14 17:18:39 -04:00
Frank babe3a0f40 wip: zen 2025-10-14 17:13:21 -04:00
Frank 29b95dee53 wip: zen 2025-10-14 17:06:49 -04:00
Frank ef9a1e911e wip: zen 2025-10-14 17:06:49 -04:00
Jay V 7eddaa806d docs: improve MCP server configuration guidance with examples and caveats 2025-10-14 16:43:59 -04:00
Dax Raad d07e79e6ad ci: channels 2025-10-14 15:09:18 -04:00
Dax Raad f17a7cde8d sync 2025-10-14 14:57:34 -04:00
GitHub Action 6d446c2a03 chore: format code 2025-10-14 18:56:54 +00:00
Dax Raad 61f6091de1 ci: test 2025-10-14 14:56:21 -04:00
Dax Raad 289783f627 ci: version stuff 2025-10-14 14:52:05 -04:00
Dax Raadandopencode 4c464cf4c0 ci: fix 2025-10-14 18:44:22 +00:00
opencode 83be5b0171 release: v0.15.3 2025-10-14 18:44:21 +00:00
Dax Raad 0c022ef39d ci: stuff 2025-10-14 14:35:04 -04:00
Aiden ClineandGitHub 717b544633 fix: false positive package manager detection in upgrade (#3181) 2025-10-14 13:18:40 -05:00
Frank c1a420717a ci: fix 2025-10-14 13:58:54 -04:00
Frank 42c2ffd842 wip: zen 2025-10-14 13:52:30 -04:00
GitHub Action 5192c51843 chore: format code 2025-10-14 17:08:18 +00:00
Adam 96d7ccea48 wip: css/ui work 2025-10-14 12:07:45 -05:00
Adam 49e859cfd6 wip: css/ui work 2025-10-14 12:06:18 -05:00
Adam 6c57a69af4 wip: desktop work 2025-10-14 12:06:17 -05:00
Netanel DraimanandGitHub 4d019430e2 feat(cli): add session option to attach command (#3167) 2025-10-14 11:04:32 -05:00
Adam 37e6c8342f wip: css and ui packages 2025-10-14 07:16:24 -05:00
Adam c04e892991 wip: desktop work 2025-10-14 07:15:08 -05:00
Adam bb82d43094 wip: desktop work 2025-10-14 07:15:08 -05:00
GitHub Action 2893b6e3a5 ignore: update download stats 2025-10-14 2025-10-14 12:04:50 +00:00
DaxandGitHub 54c3361be7 feat: use realtime events for live tool call updates in Slack (#3163) 2025-10-14 03:13:48 -04:00
Dax Raad c50cf21f18 fix: update tsconfig for Slack package 2025-10-14 02:55:21 -04:00
Dax Raad cb73e2d9e1 fix: export trimDiff function from edit tool 2025-10-14 02:55:02 -04:00
Dax Raad 48057c2c21 fix: resolve TypeScript errors in SDK and Slack package 2025-10-14 02:54:37 -04:00
Dax Raad 1923ddab6e feat: add Slack integration package with Bolt framework 2025-10-14 02:53:55 -04:00
Dax Raad b8249cde4b core: improve dependency management and error handling for more reliable builds 2025-10-14 01:33:25 -04:00
Dax Raad 19b3f3d7ce core: standardize dependency versions for better reliability
Ensures consistent versions across packages by using workspace catalog for
tailwindcss and tsconfig dependencies, reducing potential conflicts and
installation issues.
2025-10-14 01:27:17 -04:00
Dax Raad e5e05d390d core: reduce dependency conflicts by standardizing package versions through catalog
This eliminates duplicate package versions that were causing build issues and
inconsistent behavior across the monorepo. Dependencies now resolve to single
versions through the workspace catalog, making installs faster and more reliable.
2025-10-14 01:23:54 -04:00
opencode 38ad6707cf release: v0.15.2 2025-10-14 04:56:00 +00:00
Alberto FantonandGitHub 7ef246f98f fix: disable GPG signing in snapshot tests (#3102) 2025-10-13 23:40:41 -05:00
Aiden ClineandGitHub b91582d68a fix: config dir overrides (#3160) 2025-10-13 23:25:53 -05:00
Aiden ClineandGitHub 682d30bd12 fix: custom model (#3156) 2025-10-13 19:58:19 -05:00
4d68ee5d2c fix: clang formatter name (#3042)
Co-authored-by: pancake <pancake@nopcode.org>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-10-13 19:55:18 -05:00
Haris GušićandGitHub dbe9fd00b7 fix: make shell more robust (#3051) 2025-10-13 17:37:35 -05:00
mapleandGitHub cd13a8524e docs: typo in custom-tools.mdx (#3152) 2025-10-13 17:19:20 -05:00
Aiden ClineandGitHub 59765e0157 fix: typecheck (#3149) 2025-10-13 14:51:12 -05:00
d0519be0d0 fix: add useCompletionUrls option to fix certain azure setups (#2528)
Co-authored-by: andreas.blass <andreas.blass@outlook.com>
Co-authored-by: GitHub Action <action@github.com>
2025-10-13 14:16:21 -05:00
Tommy D. RossiandGitHub 066e4f064d tweak: include stack trace in server error responses (#3134) 2025-10-13 14:10:35 -05:00
opencode f81c469f17 release: v0.15.1 2025-10-13 18:14:52 +00:00
Dax Raad a398013ecb fix: disable workspace symbol lookup to prevent LSP performance issues 2025-10-13 14:05:54 -04:00
Aiden ClineandGitHub 53d9717d90 fix: pass options to compact (#3136) 2025-10-13 10:42:39 -05:00
Aiden ClineandGitHub 5885b691b9 docs: update recommended models list (#3121) 2025-10-12 21:35:31 -05:00
Aiden ClineandGitHub fd70b9b057 fix: adjust list tool prompt to handle cwd better (#3115) 2025-10-12 16:48:03 -05:00
Ravshan SamandarovandGitHub de13ccb757 docs: Update README.md (#3100) 2025-10-12 16:23:25 -04:00
JayandGitHub 7e1abb7bbf docs: Fix formatting of num_ctx in providers.mdx 2025-10-12 16:01:32 -04:00
Aiden ClineandGitHub 83afcb9c42 docs: ollama num_ctx (#3111) 2025-10-12 10:40:51 -05:00
GitHub Action afb406c5ff ignore: update download stats 2025-10-12 2025-10-12 12:04:09 +00:00
OpeOginniandGitHub 36cf9b9922 fix: add timeout to fetch models.dev refresh request (#3059) 2025-10-12 00:20:22 -05:00
opencode 0d21164255 release: v0.15.0 2025-10-12 05:12:15 +00:00
Dax Raad 3ad6f84adb ci: centralize bun setup to reduce duplication and improve caching 2025-10-12 00:46:37 -04:00
Dax Raad 24a5b16af8 ci: tweak 2025-10-12 00:40:59 -04:00
b4171aa8e8 fix: rg hanging forever when run in bash, waiting for stdin (#3103)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
2025-10-11 23:24:48 -05:00
Dax Raad d7a79733ea ci: re-enable aur 2025-10-12 00:22:16 -04:00
Frank 34e5b9bdb0 wip: zen 2025-10-11 16:17:39 -04:00
Frank d32ec9bd52 ci: fix 2025-10-11 15:08:45 -04:00
Frank 89fcfcc50b wip: zen 2025-10-11 15:07:06 -04:00
Frank 9a6fd6a5ee wip: zen 2025-10-11 14:48:34 -04:00
Frank f144a0384d ci: fix 2025-10-11 14:41:52 -04:00
Frank a67920a25e wip: zen 2025-10-11 14:38:53 -04:00
Frank 67f894e5d0 Bump sst to latest 2025-10-11 14:38:45 -04:00
Frank fc1eda5c77 wip: zen 2025-10-11 10:51:17 -04:00
Frank 371fddc820 wip: zen 2025-10-11 09:29:26 -04:00
Frank 8e89c38480 wip: zen 2025-10-11 08:27:32 -04:00
Frank b732b4caeb wip: zen 2025-10-11 08:27:32 -04:00
Frank 1940d1cf87 wip: zen 2025-10-11 08:27:32 -04:00
GitHub Action 1f0ed24402 ignore: update download stats 2025-10-11 2025-10-11 12:04:02 +00:00
Frank 133da0f448 wip: zen refactor selector 2025-10-11 07:54:57 -04:00
Frank f93e1e5c92 wip: zen fix drop down style 2025-10-11 07:15:19 -04:00
Frank ae4af54c7d wip: zen fix template 2025-10-11 06:33:47 -04:00
Dax Raad 9d30bc692c ci: fixes 2025-10-11 00:24:35 -04:00
Dax Raad 44b63dc259 ci: stuff 2025-10-11 00:06:46 -04:00
Dax Raad de2b4f6538 ci: fix 2025-10-10 23:43:32 -04:00
Frank b6b82aa847 wip: zen 2025-10-10 21:26:16 -04:00
Frank 2d35b78333 Merge branch 'console-workspaces' into dev 2025-10-10 21:24:05 -04:00
Frank c7dfbbeed0 wip: zen 2025-10-10 21:21:55 -04:00
Frank b946fd21b1 wip: zen 2025-10-10 20:32:28 -04:00
Frank daa0ca40f2 wip: zen 2025-10-10 20:30:13 -04:00
Frank 5b27130d60 wip: zen 2025-10-10 20:16:44 -04:00
Frank ee1eb35269 wip: zen 2025-10-10 20:02:17 -04:00
Frank 4dda7cc6a4 wip: zen 2025-10-10 19:56:40 -04:00
Frank cc590364e9 wip: zen 2025-10-10 19:49:59 -04:00
Frank f14cd4a3db wip: zen 2025-10-10 19:39:01 -04:00
Dax Raad 07645e0705 ci: fixes 2025-10-10 18:17:10 -04:00
Dax Raad f053862018 ci: fix 2025-10-10 18:11:19 -04:00
Dax Raad 69127aeaa0 ci: stuff 2025-10-10 18:04:08 -04:00
Dax Raad 847455383d ci: stuff 2025-10-10 17:56:33 -04:00
Dax Raad 9da95cb805 upgrade to bun 1.3.0 2025-10-10 17:53:32 -04:00
Frank 48008f91ac wip: zen 2025-10-10 16:42:27 -04:00
Frank d8b3aa9382 wip: zen 2025-10-10 16:34:07 -04:00
Frank ea9b5b8d76 wip: zen 2025-10-10 16:04:06 -04:00
Frank 4227b89ebc wip: zen 2025-10-10 14:54:49 -04:00
Frank ee846235f2 wip: zen 2025-10-10 14:19:06 -04:00
Frank 9463ce8006 wip: zen 2025-10-10 14:11:48 -04:00
Frank 756fb61691 wip: zen 2025-10-10 13:52:54 -04:00
Frank 94d0a3d888 wip: zen style members 2025-10-10 13:48:56 -04:00
Frank d83af721a6 wip: zen style api keys 2025-10-10 13:45:06 -04:00
Frank 0bc00bef32 wip: zen 2025-10-10 13:26:39 -04:00
Frank 98c13a965b wip: zen 2025-10-10 13:21:51 -04:00
Frank 310065bd0a wip: zen 2025-10-10 12:46:42 -04:00
Rustafarian DevandGitHub 34ec6cc978 fix: perl6 file extension (#3066) 2025-10-10 11:28:49 -05:00
Frank 5a90e5f9e2 wip: zen 2025-10-10 12:22:36 -04:00
Frank 5ee3063aab wip: sync 2025-10-10 12:16:57 -04:00
Frank 920373d252 wip: zen settings 2025-10-10 12:04:02 -04:00
Frank c9155c117a wip: zen 2025-10-10 09:03:49 -04:00
GitHub Action 28d617d867 ignore: update download stats 2025-10-10 2025-10-10 12:04:18 +00:00
Frank 593d0737b5 wip: zen style byok 2025-10-10 03:15:55 -04:00
Frank 64409182ec wip: zen style byok 2025-10-10 02:53:05 -04:00
Frank 8d4607ebd5 wip: zen style byok 2025-10-10 02:37:50 -04:00
Frank 250393978b wip: style byok 2025-10-10 02:34:06 -04:00
Frank fec70ae9c9 wip: zen 2025-10-10 01:36:15 -04:00
Frank ad7b4b1fcd wip: zen style nav bar 2025-10-10 00:56:16 -04:00
Frank 03d5089436 wip: zen style model 2025-10-10 00:02:04 -04:00
Dax Raad 9b52d33889 core: improve directory validation error messages to help users fix invalid directory names 2025-10-09 22:40:23 -04:00
Frank bc0e00cbb7 wip: zen style header 2025-10-09 22:38:42 -04:00
Dax Raad 096710a8cc ensure @opencode-ai/plugin is available in .opencode folder 2025-10-09 21:18:49 -04:00
opencode 50bb201187 release: v0.14.7 2025-10-10 01:02:37 +00:00
Dax Raad f211fc45a3 drop excess dependency in opencode sdk 2025-10-09 20:55:25 -04:00
Dax Raad d91781c639 core: use platform-specific watcher backends for better file system monitoring 2025-10-09 18:29:18 -04:00
Dax Raad f3b71007d2 core: replace chokidar with @parcel/watcher for better performance and cross-platform support 2025-10-09 18:21:38 -04:00
Frank 60dd987efd wip: zen 2025-10-09 17:18:55 -04:00
Dax Raad 0a96d254e8 ignore: add common build and framework directories to ignore list 2025-10-09 16:35:56 -04:00
Frank 51e9979457 wip: zen nav bar 2025-10-09 16:01:52 -04:00
Dax Raad dfc7ac4cf0 ignore: improve file ignore performance and cross-platform support
- Replace glob patterns with Set lookup for common folders to speed up matching
- Use path.sep for cross-platform compatibility on Windows/Unix systems
- Add comprehensive test coverage for nested and non-nested folder matching
- Simplify implementation by removing unnecessary caching complexity
2025-10-09 15:54:01 -04:00
Adam c2950d26f0 feat: experimental skip bootstrap 2025-10-09 14:51:11 -05:00
Aiden ClineandGitHub 47dfebf277 docs: fix bugged example (#3068) 2025-10-09 12:21:44 -05:00
Jay V f3b5021936 docs: adding tools doc 2025-10-09 13:19:51 -04:00
Jay V 7be9a84b72 docs: document ripgrep .ignore file override in tools 2025-10-09 13:19:51 -04:00
Jay V 78321a95e8 docs: adding spellcheck command 2025-10-09 13:19:51 -04:00
Aiden ClineandGitHub 225adc46ba feat: allow read tool to handle images (#3052) 2025-10-09 09:05:11 -05:00
GitHub Action eb4b5721cd ignore: update download stats 2025-10-09 2025-10-09 12:04:27 +00:00
Dax Raad 979c9ea569 lsp: fix root detection to use instance directory instead of worktree 2025-10-09 04:30:30 -04:00
Dax Raad c0bd29155d lsp: simplify language server root detection to use lock files
Improves project boundary detection by focusing on package manager lock files instead of config files, providing more reliable workspace identification across different project types.
2025-10-09 04:22:38 -04:00
Haris GušićandGitHub c5b5795636 fix: process.stdout.write instead of console.log for export cmd (#3049) 2025-10-09 00:46:19 -05:00
Frank 3ed4f1078f wip: zen 2025-10-08 22:33:20 -04:00
Frank 5b1fd7e539 wip: zen 2025-10-08 18:59:41 -04:00
Frank d18b6673e6 wip: zen 2025-10-08 17:03:42 -04:00
Frank c93c0d402d wip: zen 2025-10-08 15:20:50 -04:00
Frank b168bfe40d wip: zen 2025-10-08 13:31:15 -04:00
Jay V 1d621260ff docs: fix permission docs 2025-10-08 12:13:42 -04:00
GitHub Action a63fa64dec ignore: update download stats 2025-10-08 2025-10-08 12:04:31 +00:00
Adam 3c282c3c37 fix(tui): suggestions gap on home page 2025-10-08 06:56:18 -05:00
Dax Raad 2046f2e8e7 add free workspace 2025-10-08 02:27:01 -04:00
Frank af684c80d4 wip: zen 2025-10-08 01:14:39 -04:00
Frank 99b72eb1ea wip: zen 2025-10-08 00:03:36 -04:00
opencode 22a6849ff8 release: v0.14.6 2025-10-07 19:59:08 +00:00
Dax Raad dca3a5d80d fix issue with blank new version popup 2025-10-07 15:51:59 -04:00
Frank 508067ba5d wip: zen 2025-10-07 13:37:38 -04:00
Aiden ClineandGitHub b6c9df970a docs: troubleshooting ProviderModelNotFoundError (#3016) 2025-10-07 11:50:37 -05:00
SaiandGitHub 1f725cc3ed docs: add agent specific permission example (#3009) 2025-10-07 10:08:52 -05:00
Frank 6c99b833e4 wip: zen 2025-10-07 09:17:08 -04:00
GitHub Action cd3780b7f5 ignore: update download stats 2025-10-07 2025-10-07 12:04:53 +00:00
Dax Raad a440e09cfe core: improve MCP reliability and add status monitoring
- Added 5-second timeout to MCP client verification to prevent hanging connections
- New GET /mcp endpoint to monitor server connection status
- Automatically removes unresponsive MCP clients during initialization
2025-10-07 04:04:19 -04:00
opencode 27c211ef86 release: v0.14.5 2025-10-07 06:21:31 +00:00
Aiden ClineandGitHub cd528ae78f fix: mcp error (#3006) 2025-10-07 00:45:46 -05:00
Aiden ClineandGitHub 06c42093c8 tweak: grep tool to handle single file better (#3004) 2025-10-06 23:24:00 -05:00
Frank 0534bc0c09 wip: zen 2025-10-06 23:57:55 -04:00
Frank 4f33594b99 wip: zen 2025-10-06 23:57:54 -04:00
opencode e3f9e7785e release: v0.14.4 2025-10-07 03:32:10 +00:00
Dax Raad a20fc2dfdf ignore: 2025-10-06 23:25:01 -04:00
Dax Raad 2bf0e42367 core: restore bash command security validation to prevent accidental directory traversal
The permission validation that prevents commands from accessing paths outside the project directory was accidentally disabled, which could allow commands like 'cd ../' to escape the workspace. This restores the security check that keeps your commands safely contained within your project boundaries.
2025-10-06 23:24:18 -04:00
Dax Raad 10998d62b9 core: improve session API reliability with proper input validation 2025-10-06 19:37:44 -04:00
Dax Raad aee240150b Update todo tool to use centralized Todo module 2025-10-06 18:54:05 -04:00
Dax Raad cdd6e98af9 Add missing files and fix type aliases for opentui features 2025-10-06 18:53:35 -04:00
Dax Raad 6417edf998 Add todo list and session forking API endpoints 2025-10-06 18:51:57 -04:00
Dax Raad 9a0735de76 Add session forking functionality and simplify remove logic 2025-10-06 18:50:56 -04:00
Frank a470859f6f wip: zen 2025-10-06 17:23:10 -04:00
Frank f47c7c5a07 wip: zen 2025-10-06 17:17:02 -04:00
Frank c2f57ea74d wip: zen 2025-10-06 17:13:19 -04:00
Frank 9e8fd16e6e wip: zen 2025-10-06 17:13:19 -04:00
Jay V 1b17d8070b docs: update footer 2025-10-06 17:05:45 -04:00
Jay V 1db028dc05 docs: fix styles and zen doc, closes #2912 2025-10-06 17:00:10 -04:00
Jay V b351b75156 docs: share page css 2025-10-06 16:13:21 -04:00
GitHub Action 2faa28e162 ignore: update download stats 2025-10-06 2025-10-06 12:04:17 +00:00
Aiden ClineandGitHub bdf77701cf fix: add timeout message if command times out (#2986) 2025-10-05 23:55:01 -05:00
Mani SundararajanandGitHub 889c276558 fix: file references & grep tool for windows (#2980) 2025-10-05 14:32:07 -05:00
GitHub Action 9c6192b00d ignore: update download stats 2025-10-05 2025-10-05 12:03:55 +00:00
opencode d2a4a0375f release: v0.14.3 2025-10-05 11:22:57 +00:00
Dax Raad aced8c95f2 ci: publish 2025-10-05 07:14:52 -04:00
Dax Raad 1bb664869c ci: disable aur 2025-10-05 07:12:33 -04:00
Dax Raad 116a006ce6 sdk: simplify getting started with single createOpencode function
Makes it easier for developers to get started by providing a single function that creates both server and client, removing the need to manually coordinate separate server and client creation
2025-10-05 07:01:32 -04:00
Dax Raad f3c2d1b6c2 sdk: simplify getting started with single createOpencode function
Makes it easier for developers to get started by providing a single function that creates both server and client, removing the need to manually coordinate separate server and client creation
2025-10-05 07:00:29 -04:00
Aiden ClineandGitHub 71a7e8ef36 fix: max output tokens when using large thinking budget (#2976) 2025-10-04 23:38:41 -05:00
Dax Raad 5f7ae6477b sync 2025-10-04 21:33:47 -04:00
Aiden ClineandGitHub f41a54b4b0 fix: allow LSP filename matching when extension is missing (#2975) 2025-10-04 20:30:53 -05:00
iwauoandGitHub 080fce9601 docs: java-lsp support (#2958) 2025-10-04 11:28:09 -05:00
GitHub Action b2222cc278 ignore: update download stats 2025-10-04 2025-10-04 12:03:53 +00:00
Frank 82509e8604 wip: zen 2025-10-04 01:12:32 -04:00
Yuku KotaniandGitHub e7b6ffb314 feat: Vertex AI support; add google-vertex and google-vertex-anthropic providers (#2347) 2025-10-04 01:10:38 -04:00
Aiden ClineandGitHub 395c41b748 add command to debug config (#2962) 2025-10-03 23:07:58 -05:00
Frank a11a608760 wip: zen 2025-10-03 23:48:34 -04:00
Dax Raad 477586835a ci: try regional hostname again 2025-10-03 19:05:32 -04:00
Rovshan MuradovandGitHub 085f4adbc3 docs: Update models.mdx (#2916) 2025-10-03 17:06:20 -04:00
Frank 9671872059 wip: zen 2025-10-03 16:32:53 -04:00
Jay V 6378e6c06f docs: rename opencode to OpenCode 2025-10-03 13:46:56 -04:00
Frank 4159db4549 wip: zen 2025-10-03 12:54:52 -04:00
Adam 79764c8c4c fix: github stats 2025-10-03 09:34:17 -05:00
Adam 006cb5b36d fix: user-agent 2025-10-03 09:30:51 -05:00
Adam 8ce7d58e6d chore: user-agent header 2025-10-03 09:27:12 -05:00
Adam b622e924b6 chore: logging errors 2025-10-03 09:19:54 -05:00
Adam 8e80b8f2fa chore: logging errors 2025-10-03 09:10:33 -05:00
Adam 3fa280d218 chore: app -> desktop 2025-10-03 09:04:28 -05:00
Frank 1d58b55482 wip: zen 2025-10-03 08:25:51 -04:00
GitHub Action aae387f7dc ignore: update download stats 2025-10-03 2025-10-03 12:04:07 +00:00
Frank 60e21642a5 wip: zen 2025-10-03 07:36:16 -04:00
Frank 600b512c9c wip: zen 2025-10-03 07:36:16 -04:00
Frank 3be1f9b67e wip: zen 2025-10-03 07:36:16 -04:00
Dax Raadandopencode ad0f137e35 ci: stuff 2025-10-03 10:53:10 +00:00
opencode 253105bcf5 release: v0.14.1 2025-10-03 10:53:10 +00:00
Dax Raad bd0ba5ab88 turn on codex medium reasoning again 2025-10-03 06:46:07 -04:00
David Hill ea993976b0 Firefox email input fix 2025-10-02 23:50:51 +01:00
4c11ccd334 docs: update theme (#2929)
Co-authored-by: David Hill <iamdavidhill@gmail.com>
2025-10-02 23:20:30 +01:00
David Hill d766ca23e8 Update index.css 2025-10-02 23:19:53 +01:00
fe4589d335 ignore: Workspace updates (#2930)
Co-authored-by: David Hill <iamdavidhill@gmail.com>
2025-10-02 23:18:57 +01:00
Frank 6036a1d611 wip: zen 2025-10-02 18:16:29 -04:00
Frank a8341e2b8b wip: zen 2025-10-02 17:55:54 -04:00
Frank 73115efab1 wip: zen 2025-10-02 16:09:42 -04:00
Frank a45fa7a93c wip: zen 2025-10-02 13:58:40 -04:00
JayandGitHub ae15c91455 docs: README 2025-10-02 12:33:32 -04:00
Jay V 52f16c496b docs: update README 2025-10-02 12:31:58 -04:00
David Hill 24d9f45506 Copy tweaks 2025-10-02 17:02:33 +01:00
David Hill 2404d70a33 Border top only on safari fix 2025-10-02 16:55:48 +01:00
David Hill 26f1cc87ca Update favicon.svg 2025-10-02 16:55:29 +01:00
Aiden ClineandGitHub 860e47edea fix: run cmd json format when running command (#2926) 2025-10-02 10:37:42 -05:00
David Hill e2378f2237 Style fixes 2025-10-02 16:35:23 +01:00
David Hill 9e197a5b67 Update dock.png 2025-10-02 16:24:14 +01:00
David Hill 5f4041c58f Update dock.png 2025-10-02 16:14:52 +01:00
David Hill d56e81f02b Email input color fix 2025-10-02 16:11:55 +01:00
David Hill 6022d12ea2 Update dock.png 2025-10-02 15:50:56 +01:00
David Hill f7ef1c286f Testimonial tweaks 2025-10-02 15:37:36 +01:00
David Hill b35c6b9fff Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-10-02 15:37:13 +01:00
David Hill 30ec02e82d faq icon fix 2025-10-02 15:37:10 +01:00
Frank bc9522d5d8 ignore: fix 2025-10-02 10:10:07 -04:00
David Hill b6e80e72f6 Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-10-02 15:03:59 +01:00
David Hill 2ded2aa2d9 Body background fix 2025-10-02 15:03:56 +01:00
David Hill 30dc0cbe58 Mobile nav icon fix 2025-10-02 15:02:57 +01:00
David Hill 2bd0c9c6d2 Mobile nav icon fix 2025-10-02 15:02:44 +01:00
David Hill f9229889a1 Mobile nav fix 2025-10-02 15:01:22 +01:00
Adam eb4f55bdf6 fix: broken links 2025-10-02 09:00:33 -05:00
David Hill 9ee4e2e3d4 Update posters for videos 2025-10-02 14:55:38 +01:00
David Hill decb6ff2d3 Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-10-02 14:54:16 +01:00
David Hill b9de71dbfa Testimonial tweak 2025-10-02 14:53:54 +01:00
Adam 124e355a3c chore: add email signup back 2025-10-02 08:46:25 -05:00
David Hill 095fe68786 Update faq.tsx 2025-10-02 14:42:49 +01:00
David Hill afc67caa48 Faq icon color fix 2025-10-02 14:41:57 +01:00
Adam 189b7f1172 fix: testimonial link 2025-10-02 08:34:22 -05:00
Adam cc955098cd wip: desktop work 2025-10-02 08:34:01 -05:00
GitHub Action 8699e896e6 ignore: update download stats 2025-10-02 2025-10-02 12:04:06 +00:00
opencode ca4cb85dcd release: v0.14.0 2025-10-02 05:33:58 +00:00
Dax Raad 88474e0653 ci: fix 2025-10-02 01:25:27 -04:00
Dax Raad 5667a7ed16 ci: publsih 2025-10-02 01:24:33 -04:00
Dax Raad 2ae3231ff9 ci: test 2025-10-02 01:19:53 -04:00
Dax Raad d92fc25e26 ci: install opencode 2025-10-02 01:19:53 -04:00
Dax Raadandopencode c8c0373f1d ci: fix 2025-10-02 05:18:01 +00:00
opencode bccee29d2f release: v0.13.9 2025-10-02 05:18:01 +00:00
Dax Raad ad307f7f89 ci: sync 2025-10-02 01:09:58 -04:00
Dax Raad eac11c0753 ci: stuff 2025-10-02 01:08:29 -04:00
Aiden ClineandGitHub 0e804c302c docs: fix install fmt (#2914) 2025-10-01 23:32:39 -05:00
Aiden ClineandGitHub fb88cb0aa3 docs: fix more links (#2913) 2025-10-01 23:22:17 -05:00
8fc6a25142 chore: rm empty try-catch block (#2769)
Co-authored-by: Sandip Wane <sandip.wane@cloudhedge.io>
2025-10-01 23:21:57 -05:00
Dax Raad 5079ba7ce5 core: fix file search limit handling and ensure File module initialization 2025-10-02 00:18:18 -04:00
opencode 19cb211b62 release: v0.13.8 2025-10-02 04:16:48 +00:00
Dax Raad b2440e92e7 core: improve file search reliability and performance 2025-10-02 00:09:02 -04:00
Aiden ClineandGitHub 125624489b docs: fix (#2910) 2025-10-01 22:20:35 -05:00
Jay V 991f85c907 docs: hide email signup 2025-10-01 20:16:02 -04:00
Jay V c00fbbdcae docs: testimonials 2025-10-01 19:57:17 -04:00
Dax Raad d4e9c60af7 wip: lander 2025-10-01 19:54:58 -04:00
Jay V 0691815c0a docs: fix link 2025-10-01 19:52:31 -04:00
Dax Raad 985fd4d9a8 wip: lander 2025-10-01 19:49:00 -04:00
Dax Raad 87fa8dc70c ignore: fix 2025-10-01 19:40:56 -04:00
a782e3dac2 Zen lander (#2907)
Co-authored-by: David Hill <iamdavidhill@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: Jay V <air@live.ca>
2025-10-01 19:38:15 -04:00
Frank 70da3a9399 wip: zen 2025-10-01 19:34:37 -04:00
Frank 1024537b47 doc: update zen pricing 2025-10-01 17:48:12 -04:00
GitHub Action 2a4f21a694 ignore: update download stats 2025-10-01 2025-10-01 12:04:26 +00:00
Dax Raad 5f61945090 core: remove redundant patch integration test
The integration test was duplicating coverage already provided by the comprehensive
patch namespace tests. Users benefit from faster test runs without losing any
coverage of patch functionality. The remaining tests provide complete validation
of patch parsing, application, and tool integration.
2025-10-01 06:49:19 -04:00
Dax Raad 41ce56494b core: make patch tool more reliable and consistent with other editing tools
The patch tool now works seamlessly alongside other file editing tools with improved
error handling and a more intuitive permission system. Users will experience:

- More reliable patch application with better error messages
- Consistent permission prompts that match other editing tools
- Smoother integration when applying complex multi-file changes
- Better feedback on what changes are being made before applying patches

This refactoring leverages the robust patch parsing engine while making the tool
feel native to the opencode workflow, reducing friction when making bulk changes
to your codebase.
2025-10-01 06:45:43 -04:00
opencode 172aeaaf14 release: v0.13.7 2025-10-01 09:13:16 +00:00
Dax Raad bd69c5aca8 codex should not have reasoning effort 2025-10-01 05:06:37 -04:00
Dax Raad 6a7eeb39c3 core: prevent file deletion when reverting changes to existing files 2025-10-01 05:06:37 -04:00
opencode 35a608cd53 release: v0.13.6 2025-10-01 07:44:18 +00:00
Dax Raad 6e19200fca overhaul file search and support @ mentioning directories 2025-10-01 03:37:01 -04:00
Aiden ClineandGitHub fe45a76c55 fix: adjust model dialog to handle same model id but different names (#2881) 2025-09-30 11:43:57 -05:00
GitHub Action bdac22cb07 ignore: update download stats 2025-09-30 2025-09-30 12:04:27 +00:00
Dax Raad 5a507023a6 update anthropic system prompts 2025-09-30 04:41:36 -04:00
Aiden ClineandGitHub c398485213 fix: tui stuck saying generating... even when it is done (#2872) 2025-09-29 23:55:47 -05:00
Aiden ClineandGitHub bc9ff7e99f fix: worktree cmd (#2870) 2025-09-29 22:21:54 -05:00
Frank 7447460b5a wip: zen 2025-09-29 14:17:53 -04:00
opencode 5345c828ca release: v0.13.5 2025-09-29 14:12:58 +00:00
Aiden ClineandGitHub edeaab321a fix: bash regex (#2858) 2025-09-29 08:51:46 -05:00
GitHub Action 478ead6a05 ignore: update download stats 2025-09-29 2025-09-29 12:04:29 +00:00
Giuseppe RotaandGitHub 468201190e docs: document model id behavior (#2856) 2025-09-29 06:52:26 -05:00
opencode cc0d460904 release: v0.13.4 2025-09-29 05:53:07 +00:00
Dax Raad f8ab0de0ad ci: fix homebrew 2025-09-29 01:40:27 -04:00
Dax Raad 322363f11b release: v0.13.2 2025-09-29 01:38:53 -04:00
Dax Raad acd33c2fc5 ci: publish 2025-09-29 01:24:35 -04:00
Dax Raad b6fba03a7d ci: fix 2025-09-29 01:22:39 -04:00
Dax Raad fbced21b8e ci: fix 2025-09-29 01:06:12 -04:00
Aiden ClineandGitHub e7cb5d8345 ignore: go mod tidy (#2851) 2025-09-28 23:05:56 -05:00
Frank 918739057d wip: zen 2025-09-28 19:55:40 -04:00
Frank e3a7096e44 wip: zen 2025-09-28 19:55:40 -04:00
Dax Raad c148f10bbd core: improve webfetch tool content negotiation and format handling 2025-09-28 17:57:50 -04:00
Frank 06495ea964 wip: zen 2025-09-28 12:49:28 -04:00
GitHub Action b64cecb079 ignore: update download stats 2025-09-28 2025-09-28 12:03:57 +00:00
Frank e10bb58cb3 wip: zen 2025-09-27 21:53:50 -04:00
Aiden ClineandGitHub 89167ae387 respect model id in opencode.json (#2833) 2025-09-27 17:09:21 -05:00
Aurélien TollardandGitHub 4b429029df Fix: Set OPENCODE_CALLER env in a more portable way for vscode extension (#2230) 2025-09-27 10:36:24 -04:00
Frank c7e5d29109 wip: zen 2025-09-27 10:19:58 -04:00
Frank a564267b29 wip: zen 2025-09-27 10:05:19 -04:00
GitHub Action 594bdb43c2 ignore: update download stats 2025-09-27 2025-09-27 12:04:01 +00:00
Dax Raad ea66c02633 ci: tweaks 2025-09-27 04:12:55 -04:00
Dax Raad 925ce6503e sync 2025-09-27 04:10:56 -04:00
Arjun SinghandGitHub 8a28d34fe9 Include step-start and step-finish for cost tracking (#2810) 2025-09-27 03:45:36 -04:00
Dax Raad 8bea479df9 ci: wtf 2025-09-27 03:20:08 -04:00
Dax Raad 468d919a92 ci: fix 2025-09-27 03:19:34 -04:00
Dax Raad 7e5527379d core: configure turbo to avoid building opencode for web tests 2025-09-27 03:19:29 -04:00
Dax Raad fcbc78180b ci: fix 2025-09-27 03:18:12 -04:00
Dax Raad bab1ca54e4 ci: test 2025-09-27 03:17:22 -04:00
Dax Raad d644e0b8a7 core: fix config test by removing model field expectation 2025-09-27 03:10:01 -04:00
Dax Raad e54ec45002 ci: fix git identity in test workflow 2025-09-27 03:07:37 -04:00
Dax Raad 4b94d98f89 ci: improve test coverage 2025-09-27 03:04:42 -04:00
Dax Raad d0043a4a78 sync 2025-09-27 02:53:20 -04:00
Dax Raad 26ebf85b0e ci: format 2025-09-27 02:22:03 -04:00
Dax Raad 53481f9790 wip: bun test improvements 2025-09-27 02:17:08 -04:00
Dax Raad eadc2a8535 ci: give up 2025-09-27 01:51:54 -04:00
Dax Raad 00a5ec5bd2 ci: add regional hostname 2025-09-27 01:28:11 -04:00
Dax Raad 0b6b9062d9 fix zen cookie 2025-09-27 01:12:25 -04:00
opencode c450549d0f release: v0.12.1 2025-09-26 21:18:45 +00:00
Frank 1ba0155943 zen: accept tax id 2025-09-26 17:10:45 -04:00
Timo ClasenandGitHub 3d332a06b5 fix(tool): follow symlinks when looking for tools (#2809) 2025-09-26 16:01:08 -05:00
opencode f709e0b48b release: v0.12.0 2025-09-26 20:55:00 +00:00
Frank 57e1bffbd5 zen: model management helper 2025-09-26 15:18:24 -04:00
f321661b4c docs: add TUI configuration options and examples (#2212)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Jay <air@live.ca>
2025-09-26 13:09:46 -04:00
Yihui KhuuandGitHub 7ecdc1b5d8 fix: config loading not considering symlinks (#2800) 2025-09-26 09:46:49 -05:00
GitHub Action 39917a35ce ignore: update download stats 2025-09-26 2025-09-26 12:04:26 +00:00
Dax Raadandopencode bfe3f03e03 ci: fix deploy 2025-09-26 11:57:49 +00:00
opencode d01af65dbc release: v0.11.8 2025-09-26 11:57:49 +00:00
Dax Raad 80305813f5 disable aggressive config validation 2025-09-26 07:51:53 -04:00
opencode 061877e275 release: v0.11.7 2025-09-26 11:19:15 +00:00
Adam 05e6c3d8a0 fix(tui): cursor position 2025-09-26 06:13:23 -05:00
Dax Raad 093fbca711 core: add themes to allowed config directories 2025-09-26 06:40:41 -04:00
opencode 81deea855f release: v0.11.6 2025-09-26 09:52:23 +00:00
Dax Raad 5c67bebf86 tui: fix cursor position offset in home screen 2025-09-26 05:46:16 -04:00
opencode 9cc1f2884f release: v0.11.5 2025-09-26 09:40:16 +00:00
Dax Raad f2b547cc45 fix erroring on custom tool folder 2025-09-26 05:33:38 -04:00
Dax Raad 70310a37b3 validate config directory 2025-09-26 03:23:25 -04:00
Dax Raad eb7f4e20df core: add config update endpoint and functionality 2025-09-26 02:37:19 -04:00
Dax Raad ea21bfd3c6 ci: ignore 2025-09-26 02:01:19 -04:00
Dax Raad 22d5be9bf8 ci: setup husky pre-push hook to run typecheck 2025-09-26 02:01:19 -04:00
opencode 1c878c662b release: v0.11.4 2025-09-26 05:56:03 +00:00
Dax Raad 55d154d4ac tui: fix opencode logo spacing in home view 2025-09-26 01:40:32 -04:00
Dax Raad f5c7a94abe turn reasoning summaries back on by default for zen 2025-09-26 01:37:44 -04:00
Dax Raad 7ec3900208 core: enable reasoning.encrypted_content and reasoningSummary for opencode provider\ntui: adjust editorY position calculation 2025-09-26 01:27:53 -04:00
Aiden ClineandGitHub 5d95846df1 fix: openai reasoning issue (#2780) 2025-09-26 01:23:30 -04:00
Aiden ClineandGitHub d47feb9969 tweak: include usage by default for openai compatible providers (#2788) 2025-09-25 21:06:58 -05:00
David Hill 8f135d13e3 Update opencode logo 2025-09-25 23:22:50 +01:00
Frank f9ab4102f6 zen: track tps 2025-09-25 17:56:41 -04:00
Frank f9117bcc7f zen: check balance on enable billing 2025-09-25 17:47:50 -04:00
Frank 6e712f9faf zen: fix parsing cache write tokens 2025-09-25 17:02:23 -04:00
Adam b207ed2b7b wip: better desktop file status state and timeline 2025-09-25 14:41:31 -05:00
Adam 945de4eddc wip: watch select .git files in watcher 2025-09-25 14:41:31 -05:00
GitHub Action cd655177d9 ignore: update download stats 2025-09-25 2025-09-25 12:04:27 +00:00
Frank 8f90497fc4 zen: billing 2025-09-24 21:26:04 -04:00
GitHub Action 9659efca46 chore: format code 2025-09-24 23:10:17 +00:00
Frank d0377a95cf zen: billing 2025-09-24 19:09:28 -04:00
Adam 3b20bf6d4f fix(app): changes view 2025-09-24 15:49:40 -05:00
Adam c3e52580b0 feat(app): changes view 2025-09-24 15:46:33 -05:00
Adam 2badfcdcf4 fix: select dialog hover 2025-09-24 15:08:58 -05:00
Adam f589fc2327 feat: fuzzy file open 2025-09-24 12:40:54 -05:00
d3b6545e7c feat(app): added command palette (#2630)
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
2025-09-24 11:05:15 -05:00
GitHub Action 3f911b22b0 ignore: update download stats 2025-09-24 2025-09-24 12:04:37 +00:00
opencode 5199141369 release: v0.11.3 2025-09-24 03:43:46 +00:00
Dax Raad d86d3e7ea1 update copilot auth 2025-09-23 23:36:27 -04:00
GitHub Action fe8d29cb2b chore: format code 2025-09-23 21:59:09 +00:00
Frank edd6198999 zen: refund 2025-09-23 17:58:27 -04:00
GitHub Action c3b2c27997 chore: format code 2025-09-23 21:37:20 +00:00
Jay V 679aeb29f0 docs: add codex to zen 2025-09-23 17:36:40 -04:00
Jay V 190413580f docs: edit 2025-09-23 17:34:52 -04:00
Jay V 8c9fbc7717 docs: edits 2025-09-23 17:34:52 -04:00
Jay V 9d3fdda674 docs: edit 2025-09-23 17:34:52 -04:00
449994f120 feat: output-format flag to stream json output (#2471)
Co-authored-by: Siddhant Choudhary <sid@treaps.com>
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-23 16:19:32 -05:00
opencode d772fff776 release: v0.11.2 2025-09-23 21:03:59 +00:00
Dax Raad 71b43fd02e fix codex errors 2025-09-23 16:56:40 -04:00
Dax Raad f40b91ab7a fix: remove file existence check from LSP debug and format storage code 2025-09-23 16:49:57 -04:00
6404bd006d ignore: more reliable install script, handle non prettified json responses (#2745)
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-23 14:58:04 -05:00
Frank 75157e515c wip: remove 2025-09-23 14:21:39 -04:00
Frank 5a96ee8e1b zen: update logged endpoints 2025-09-23 14:21:39 -04:00
Adam ee6ceb4c64 fix: open text files 2025-09-23 12:43:24 -05:00
David Hill 9d53628e19 Merge branch 'dev' of https://github.com/sst/opencode into dev 2025-09-23 18:36:27 +01:00
David Hill 869b476145 ignore: Copy update 2025-09-23 18:35:42 +01:00
David Hill 223d487787 ignore: Footer update 2025-09-23 18:30:06 +01:00
Adam 5ead6d7dd5 fix: exclude generated css file 2025-09-23 12:08:49 -05:00
GitHub Action a98454217f chore: format code 2025-09-23 17:05:32 +00:00
Adam cbb75d8577 fix: theme css format 2025-09-23 12:04:50 -05:00
GitHub Action 4ab992a9a9 chore: format code 2025-09-23 16:41:57 +00:00
Adam 80b0a93d64 wip: desktop file updates 2025-09-23 11:41:15 -05:00
Grégoire ParisandGitHub e749d48534 docs: fix grammar mistake in lsp docs(#2744) 2025-09-23 08:12:46 -05:00
GitHub Action d7e873f807 ignore: update download stats 2025-09-23 2025-09-23 12:04:24 +00:00
Aiden ClineandGitHub c23510346b ignore: lsp debug file check (#2743) 2025-09-22 22:16:03 -05:00
Aiden ClineandGitHub f9c5df05a1 docs: github copilot model enable note (#2741) 2025-09-22 21:29:16 -05:00
Aiden ClineandGitHub 02b4d1e2fc fix: lsp extension undefined handle (#2739) 2025-09-22 21:14:55 -05:00
Joseph HansonandGitHub 0b36eb8760 docs: fix permissions link (#2738) 2025-09-22 20:28:54 -05:00
Adam HoskerandGitHub 36bec9948c docs: Add editor setup tip (#2638) 2025-09-22 16:01:27 -04:00
GitHub Action 2db73c39df chore: format code 2025-09-22 19:59:29 +00:00
Jay V 6107666d04 docs: edit tools doc 2025-09-22 15:58:48 -04:00
Aiden ClineandGitHub cc2bd7141f fix: enforce extensions requirement for custom lsp servers (#2734) 2025-09-22 11:45:47 -05:00
GitHub Action ee442975df ignore: update download stats 2025-09-22 2025-09-22 12:04:25 +00:00
Dax Raad 9b1a508657 ci: bump 2025-09-22 01:47:28 -04:00
Dax Raad 288c977596 ci: snapshot builds 2025-09-22 01:45:23 -04:00
6b799b304c feat: add Java LSP server support (#2547)
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-21 23:55:15 -05:00
Aiden ClineandGitHub 92c126d875 fix: lsp spawn logic (#2723) 2025-09-21 11:25:47 -05:00
GitHub Action 7123fbeb47 ignore: update download stats 2025-09-21 2025-09-21 12:04:06 +00:00
opencode 84bb692193 release: v0.11.1 2025-09-21 08:51:11 +00:00
Dax Raad 079095d7a9 core: filter models without keys in opencode provider 2025-09-21 04:43:32 -04:00
opencode 28e1d67ea4 release: v0.11.0 2025-09-21 08:04:21 +00:00
GitHub Action c1940d1d2c chore: format code 2025-09-21 04:23:40 +00:00
Frank 869f629c14 wip: zen 2025-09-21 00:23:05 -04:00
Frank a55943e469 wip: zen 2025-09-21 00:06:50 -04:00
Aiden ClineandGitHub 84d95a0d2a ignore: lsp log (#2715) 2025-09-20 23:02:06 -05:00
opencode 7dfed8ca35 release: v0.10.4 2025-09-20 23:00:32 +00:00
Dax Raad 38ea0fc051 turn back on compaction summaries 2025-09-20 18:52:30 -04:00
9223b6ed8f Enhance theme documentation with links (#2707)
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-20 11:25:12 -05:00
GitHub Action f8528c52d9 ignore: update download stats 2025-09-20 2025-09-20 12:04:03 +00:00
Aiden ClineandGitHub d63ce40af2 fix: no payment method (#2706) 2025-09-20 04:15:44 -04:00
Jay V 5acdd70587 docs: zen 2025-09-19 20:13:57 -04:00
opencode b04df6c0d2 release: v0.10.3 2025-09-19 21:22:00 +00:00
GitHub Action f1cbdf441c chore: format code 2025-09-19 18:18:56 +00:00
Frank 9420d80b73 zen: data share 2025-09-19 14:16:53 -04:00
Aiden ClineandGitHub c21161b75e docs: fix bad docs (#2691) 2025-09-19 12:40:40 -05:00
GitHub Action aaff066457 chore: format code 2025-09-19 17:29:44 +00:00
Jay V c7fbf9de44 ignore: zen 2025-09-19 13:29:04 -04:00
Adam d88c17dad0 wip: desktop progress 2025-09-19 10:53:49 -05:00
opencode f57c3f7cf6 release: v0.10.2 2025-09-19 15:18:11 +00:00
Adam 2460108223 fix: remove grok msg 2025-09-19 09:59:47 -05:00
Adam 84e8eea52e wip: desktop cleanup 2025-09-19 09:55:46 -05:00
Adam 9efc2eaf2e wip: desktop cleanup 2025-09-19 09:42:39 -05:00
Adam 37e2644452 wip: desktop visual tweaks 2025-09-19 09:38:10 -05:00
neriousyandAdam 22a78cf13f chore: opencode favicon 2025-09-19 09:33:28 -05:00
GitHub Action 2e9806b320 chore: format code 2025-09-19 14:32:55 +00:00
Adam ba839d4446 chore: normalize theme hex 2025-09-19 09:32:19 -05:00
GitHub Action 2bec21d81d chore: format code 2025-09-19 12:19:13 +00:00
Adam e5271f3d1a wip: desktop work 2025-09-19 07:18:39 -05:00
Adam 1edb23c2c7 wip: desktop work 2025-09-19 07:18:39 -05:00
Adam b1e6b9c7c9 wip: desktop work 2025-09-19 07:18:39 -05:00
Adam 20cb5a7c56 wip: desktop starting state 2025-09-19 07:18:38 -05:00
GitHub Action b1d44482bc ignore: update download stats 2025-09-19 2025-09-19 12:04:16 +00:00
GitHub Action e11102c9df chore: format code 2025-09-19 10:14:30 +00:00
Dax Raad 7be9dc8e49 ignore: fix 2025-09-19 06:13:45 -04:00
Dax Raad 824e035815 ci: stuff 2025-09-19 06:10:27 -04:00
GitHub Action d652b94a14 chore: format code 2025-09-19 09:29:24 +00:00
Dax Raad ebef2ea2d0 ci: stuff 2025-09-19 05:28:46 -04:00
GitHub Action b5b8a0555d chore: format code 2025-09-19 09:12:20 +00:00
Dax Raad ae6154e1c3 ignore: rework bootstrap so server lazy starts it 2025-09-19 05:11:29 -04:00
opencode 0e19ca21ed release: v0.10.1 2025-09-19 05:15:32 +00:00
Dax Raad baaff81a06 fix task tool ui disappearing once done 2025-09-19 01:09:52 -04:00
Aiden ClineandGitHub ffa5689885 docs: subtask config option (#2682) 2025-09-18 17:52:23 -05:00
Aiden ClineandGitHub 0e409842e8 docs: rm incorrect lsp mention (#2677) 2025-09-18 16:08:50 -05:00
opencode 5a7a725787 release: v0.10.0 2025-09-18 20:51:03 +00:00
GitHub Action f277512938 chore: format code 2025-09-18 14:59:48 +00:00
Frank 4ceabdffa0 wip: zen 2025-09-18 10:59:01 -04:00
GitHub Action c87480cf93 ignore: update download stats 2025-09-18 2025-09-18 12:04:18 +00:00
Timo ClasenandGitHub 0df6fc1226 fix(config): keybinds should not be required in config schema (#2669) 2025-09-18 06:30:44 -05:00
GitHub Action 32ba2e02aa chore: format code 2025-09-18 09:43:35 +00:00
Dax Raad 1ffc8be2b6 rework custom tools 2025-09-18 05:42:59 -04:00
Dax Raad 5f2945ae71 docs: add custom tools section to plugins documentation 2025-09-18 04:29:08 -04:00
DaxandGitHub 65baf76df6 Plugin tool updates (#2670) 2025-09-18 04:26:57 -04:00
DaxandGitHub 3b6c0ec0b3 support custom tools (#2668) 2025-09-18 03:58:21 -04:00
Frank e9d902d844 wip: zen 2025-09-18 01:36:54 -04:00
GitHub Action e8b4f593a6 chore: format code 2025-09-18 05:33:32 +00:00
Frank fc4f281408 wip: zen 2025-09-18 01:32:40 -04:00
GitHub Action f8c4f713a5 chore: format code 2025-09-18 03:39:57 +00:00
Jason QuenseandGitHub 63c8874d2d fix: type exports in package.json for SDK package (#2654) 2025-09-17 23:39:26 -04:00
71076d5c68 fix: add synthetic user prompt after session compaction (#2659)
Co-authored-by: Julián Díaz <git@jdiaz.io>
2025-09-17 23:27:37 -04:00
Frank 0319043b49 Support GLM coding plan 2025-09-17 16:54:00 -04:00
Frank e0334d5569 wip: zen 2025-09-17 16:03:47 -04:00
Aiden ClineandGitHub ff6a93f355 fix: only keep aborted messages if they have sufficient parts (#2651) 2025-09-17 14:24:53 -05:00
opencode 733b21e22b release: v0.9.11 2025-09-17 16:29:48 +00:00
Aiden ClineandGitHub 3c3d6b65c2 Revert "fix: type 'reasoning' was provided without its required follo… (#2648) 2025-09-17 11:17:26 -05:00
opencode 9ca48d3a39 release: v0.9.10 2025-09-17 14:54:25 +00:00
Timo ClasenandGitHub 16f9edc1a0 fix(TUI): display correct branch name in git worktree (#2626) 2025-09-17 09:46:18 -05:00
Aiden ClineandGitHub 8c2aec43b8 fix: type 'reasoning' was provided without its required following item (#2633) 2025-09-17 09:45:13 -05:00
Aiden ClineandGitHub 2564801bde tweak: adjust title gen when using models like gpt-5-nano on non open… (#2646) 2025-09-17 08:39:34 -05:00
GitHub Action 7c99a03493 ignore: update download stats 2025-09-17 2025-09-17 12:04:20 +00:00
opencode 0e0460f6c0 release: v0.9.9 2025-09-17 07:40:40 +00:00
Dax Raad 8acd537d1d ci: turborepo typecheck 2025-09-17 03:33:54 -04:00
Dax Raad 40c206c2f9 add opencode attach command to connect to a remote opencode server 2025-09-17 03:30:25 -04:00
Dax Raad 259c722208 only prune messages from more than 2 turns ago 2025-09-17 03:30:09 -04:00
opencode e618cbc447 release: v0.9.8 2025-09-17 07:14:33 +00:00
Dax Raad abd99aeb7d ignore: fix event type gen 2025-09-17 01:17:56 -04:00
opencode ad5fc76b11 release: v0.9.7 2025-09-17 05:09:08 +00:00
Dax Raad ff1f4d6bf9 disable reading .env file automatically 2025-09-17 01:02:23 -04:00
GitHub Action 170ea9c32b chore: format code 2025-09-16 23:53:59 +00:00
Jay V 65ced67432 ignore: zen 2025-09-16 19:53:18 -04:00
Jay V 9f46068c57 ignore: mobile styles zen 2025-09-16 19:39:36 -04:00
Jay V 479cf2fa4f ignore: zen 2025-09-16 19:39:36 -04:00
Frank 39c54f367f wip: zen 2025-09-16 18:13:05 -04:00
Frank 8c71107a93 wip: zen 2025-09-16 17:49:39 -04:00
GitHub Action ef10097329 chore: format code 2025-09-16 21:17:56 +00:00
Jay V 36ee4b5ede ignore: zen 2025-09-16 17:17:17 -04:00
Jay V ae84d5a734 ignore: zen 2025-09-16 17:17:17 -04:00
GitHub Action cd53770734 chore: format code 2025-09-16 20:17:16 +00:00
Jay V 4b1eca73eb ignore: zen 2025-09-16 16:16:30 -04:00
opencode fffcf69cd4 release: v0.9.6 2025-09-16 17:56:45 +00:00
Dax Raad d4c01f858b disable thinking for opencode zen and gpt-5 temporarily 2025-09-16 13:49:37 -04:00
GitHub Action 8e17570c53 chore: format code 2025-09-16 17:35:32 +00:00
Jay V 7f9d08b556 docs: zen 2025-09-16 13:26:49 -04:00
Frank 32a045f60b wip: zen 2025-09-16 09:01:13 -04:00
Aiden ClineandGitHub 91adc3cd41 docs: remove dup section (#2629) 2025-09-16 07:30:29 -05:00
GitHub Action 2bb9b4212f ignore: update download stats 2025-09-16 2025-09-16 12:04:17 +00:00
opencode 3472a50928 release: v0.9.5 2025-09-16 08:58:35 +00:00
Dax Raad 3aeac02bf1 enable session pruning and allow disabling with OPENCODE_DISABLE_PRUNE 2025-09-16 04:53:17 -04:00
opencode 52fcdcc37b release: v0.9.4 2025-09-16 08:35:55 +00:00
Dax Raad 78d6b3a963 fix crash when todo content is empty fixes #2622 2025-09-16 04:28:35 -04:00
15df2710fa fix(windows): force npm cmd shim generation and update install docs (#2558)
Co-authored-by: Dax <mail@thdxr.com>
Co-authored-by: GitHub Action <action@github.com>
2025-09-16 03:40:19 -04:00
opencode 02e492f6eb release: v0.9.3 2025-09-16 07:16:25 +00:00
Dax Raad 2d5bd26a59 feat: enhance provider model mapping and reasoning capabilities
- Add npm package tracking to provider model mapping
- Implement special handling for opencode provider with reasoning
- Update provider options mapping to use npm package names
2025-09-16 03:10:17 -04:00
opencode 8f58fef5ad release: v0.9.2 2025-09-16 04:29:00 +00:00
14cb2d2af6 feat: improve file watcher with chokidar and better ignore patterns (#2621)
Co-authored-by: GitHub Action <action@github.com>
2025-09-16 00:17:10 -04:00
Stephen MurrayandGitHub 52fb571739 fix: restore chat.message plugin hook (#2619) 2025-09-15 21:44:07 -05:00
GitHub Action 51c647ca89 chore: format code 2025-09-16 01:06:51 +00:00
Jay V 52fa7840c2 docs: zen 2025-09-15 21:05:47 -04:00
Frank 2c61b39088 wip: zen 2025-09-15 19:37:55 -04:00
Frank 6c02d4ce66 wip: zen 2025-09-15 19:26:46 -04:00
GitHub Action 11154ba697 chore: format code 2025-09-15 23:19:50 +00:00
Jay V f8ca524bf7 ignore: zen 2025-09-15 19:19:10 -04:00
GitHub Action 56222fff3c chore: format code 2025-09-15 23:03:41 +00:00
Jay V 74f9fcea88 ignore: zen 2025-09-15 19:02:51 -04:00
Frank bc213e1a61 wip: zen 2025-09-15 18:47:04 -04:00
Frank d795a38fc7 wip: zen 2025-09-15 18:44:21 -04:00
opencode 96698ea070 release: v0.9.1 2025-09-15 22:31:44 +00:00
Dax Raad 6fff10b670 docs: zen 2025-09-15 18:21:03 -04:00
Frank 194aea8e54 wip: zen 2025-09-15 18:14:07 -04:00
Frank b6d2046b0e wip: zen 2025-09-15 17:37:07 -04:00
Frank 910ea84360 wip: zen 2025-09-15 17:07:48 -04:00
Frank bc2e4e23c9 wip: zen 2025-09-15 15:53:17 -04:00
GitHub Action f5e75606e3 chore: format code 2025-09-15 19:39:00 +00:00
Jay V 0707890359 docs: zen 2025-09-15 15:38:23 -04:00
Frank 6dbba8e326 wip: zen 2025-09-15 15:21:06 -04:00
GitHub Action 413c9d9ad1 chore: format code 2025-09-15 18:50:30 +00:00
Frank 5e6dd312eb wip: zen 2025-09-15 14:48:02 -04:00
Frank 7218a662ab wip: zen 2025-09-15 14:48:02 -04:00
GitHub Action d947df3069 ignore: update download stats 2025-09-15 2025-09-15 12:04:17 +00:00
GitHub Action 5bb1f5f0a0 chore: format code 2025-09-15 07:54:04 +00:00
Dax Raad d38594d34a ci: sync 2025-09-15 03:53:27 -04:00
Dax Raad 925284c6c1 ci: sync 2025-09-15 03:53:21 -04:00
GitHub Action e716271466 chore: format code 2025-09-15 07:31:02 +00:00
Dax Raad df046e5e04 ci: typecheck 2025-09-15 03:30:26 -04:00
Dax Raad e0bfbcb663 ci: format 2025-09-15 03:28:53 -04:00
GitHub Action c1c6aca31e chore: format code 2025-09-15 07:28:34 +00:00
725104572e feat: add desktop/web app package (#2606)
Co-authored-by: adamdotdevin <2363879+adamdottv@users.noreply.github.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-09-15 03:28:08 -04:00
opencode 4954edf8ae release: v0.9.0 2025-09-15 07:18:49 +00:00
c1b4e1f19d Upgrade to Zod v4 (#2605)
Co-authored-by: GitHub Action <action@github.com>
2025-09-15 03:12:07 -04:00
Aiden ClineandGitHub 89d820b1c4 fix: visual token bug (#2603) 2025-09-14 21:23:52 -05:00
Aiden ClineandGitHub e3e459fc50 fix: reasoning metadata persistence (#2602) 2025-09-14 16:28:06 -05:00
Tommy D. RossiandGitHub 4bf0541bd6 log bash output when using opencode run (#2595) 2025-09-14 09:03:40 -05:00
Aiden ClineandGitHub c81624aef7 tweak: make bash permissions key off of command pattern (#2592) 2025-09-14 09:01:57 -05:00
Kenn CostalesandGitHub df61aa801b fix: fix wrong tool references LS and Agent (#2466) 2025-09-14 08:53:50 -05:00
GitHub Action 6af0c2ec21 ignore: update download stats 2025-09-14 2025-09-14 12:03:54 +00:00
Dax Raad ce9d2ee04f ci: script 2025-09-14 02:07:58 -04:00
1736 changed files with 73177 additions and 11371 deletions
+59
View File
@@ -0,0 +1,59 @@
name: Bug report
description: Report an issue that should be fixed
labels: ["bug"]
body:
- type: textarea
id: description
attributes:
label: Description
description: Describe the bug you encountered
placeholder: What happened?
validations:
required: true
- type: input
id: opencode-version
attributes:
label: OpenCode version
description: What version of OpenCode are you using?
validations:
required: false
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: How can we reproduce this issue?
placeholder: |
1.
2.
3.
validations:
required: false
- type: textarea
id: screenshot-or-link
attributes:
label: Screenshot and/or share link
description: Run `/share` to get a share link, or attach a screenshot
placeholder: Paste link or drag and drop screenshot here
validations:
required: false
- type: input
id: os
attributes:
label: Operating System
description: what OS are you using?
placeholder: e.g., macOS 26.0.1, Ubuntu 22.04, Windows 11
validations:
required: false
- type: input
id: terminal
attributes:
label: Terminal
description: what terminal are you using?
placeholder: e.g., iTerm2, Ghostty, Alacritty, Windows Terminal
validations:
required: false
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: 💬 Discord Community
url: https://discord.gg/opencode
about: For quick questions or real-time discussion. Note that issues are searchable and help others with the same question.
@@ -0,0 +1,20 @@
name: 🚀 Feature Request
description: Suggest an idea, feature, or enhancement
labels: [discussion]
title: "[FEATURE]:"
body:
- type: checkboxes
id: verified
attributes:
label: Feature hasn't been suggested before.
options:
- label: I have verified this feature I'm about to request hasn't been suggested before.
required: true
- type: textarea
attributes:
label: Describe the enhancement you want to request
description: What do you want to change or add? What are the benefits of implementing this? Try to be detailed so we can understand your request better :)
validations:
required: true
+11
View File
@@ -0,0 +1,11 @@
name: Question
description: Ask a question
labels: ["question"]
body:
- type: textarea
id: question
attributes:
label: Question
description: What's your question?
validations:
required: true
+20
View File
@@ -0,0 +1,20 @@
name: "Setup Bun"
description: "Setup Bun with caching and install dependencies"
runs:
using: "composite"
steps:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Cache ~/.bun
id: cache-bun
uses: actions/cache@v4
with:
path: ~/.bun
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lockb', 'bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install
shell: bash
+1 -5
View File
@@ -15,11 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.21
- run: bun install
- uses: ./.github/actions/setup-bun
- run: bun sst deploy --stage=${{ github.ref_name }}
env:
+2 -5
View File
@@ -1,4 +1,4 @@
name: Format
name: format
on:
push:
@@ -20,13 +20,10 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.21
uses: ./.github/actions/setup-bun
- name: run
run: |
bun install
./script/format.ts
env:
CI: true
+4 -2
View File
@@ -8,7 +8,9 @@ jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
contains(github.event.comment.body, ' /opencode')
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
@@ -24,4 +26,4 @@ jobs:
env:
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
with:
model: opencode/sonic
model: opencode/kimi-k2
+1 -4
View File
@@ -19,16 +19,13 @@ jobs:
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.2.21
- uses: ./.github/actions/setup-bun
- run: git fetch --force --tags
- run: bun install -g @vscode/vsce
- name: Publish
run: |
bun install
./script/publish
working-directory: ./sdks/vscode
env:
+6 -14
View File
@@ -35,18 +35,7 @@ jobs:
cache: true
cache-dependency-path: go.sum
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.2.21
- name: Cache ~/.bun
id: cache-bun
uses: actions/cache@v3
with:
path: ~/.bun
key: ${{ runner.os }}-bun-1-2-21-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-1-2-21-
- uses: ./.github/actions/setup-bun
- name: Install makepkg
run: |
@@ -60,14 +49,17 @@ jobs:
git config --global user.email "opencode@sst.dev"
git config --global user.name "opencode"
ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts || true
- name: Install dependencies
run: bun install
- name: Install OpenCode
run: curl -fsSL https://opencode.ai/install | bash
- name: Publish
run: |
./script/publish.ts
env:
OPENCODE_BUMP: ${{ inputs.bump }}
OPENCODE_CHANNEL: latest
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
+34
View File
@@ -0,0 +1,34 @@
name: snapshot
on:
push:
branches:
- dev
- opentui
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: git fetch --force --tags
- uses: actions/setup-go@v5
with:
go-version: ">=1.24.0"
cache: true
cache-dependency-path: go.sum
- uses: ./.github/actions/setup-bun
- name: Publish
run: |
./script/publish.ts
env:
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -3
View File
@@ -16,9 +16,7 @@ jobs:
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
uses: ./.github/actions/setup-bun
- name: Run stats script
run: bun script/stats.ts
+30
View File
@@ -0,0 +1,30 @@
name: test
on:
push:
branches-ignore:
- production
pull_request:
branches-ignore:
- production
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: run
run: |
git config --global user.email "bot@opencode.ai"
git config --global user.name "opencode"
bun turbo typecheck
bun turbo test
env:
CI: true
+2 -7
View File
@@ -1,4 +1,4 @@
name: Typecheck
name: typecheck
on:
pull_request:
@@ -13,12 +13,7 @@ jobs:
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.21
- name: Install dependencies
run: bun install
uses: ./.github/actions/setup-bun
- name: Run typecheck
run: bun typecheck
+2
View File
@@ -8,3 +8,5 @@ node_modules
openapi.json
playground
tmp
dist
.turbo
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
bun run typecheck
+1 -1
View File
@@ -13,7 +13,7 @@ avoid repeating the title of the page, should be 5-10 words long
Chunks of text should not be more than 2 sentences long
Each section is spearated by a divider of 3 dashes
Each section is separated by a divider of 3 dashes
The section titles are short with only the first letter of the word capitalized
+11
View File
@@ -1,3 +1,7 @@
---
description: Git commit and push
---
commit and push
make sure it includes a prefix like
@@ -7,3 +11,10 @@ core:
ci:
ignore:
wip:
For anything in the packages/web use the docs: prefix.
For anything in the packages/app use the ignore: prefix.
prefer to explain WHY something was done from an end user perspective instead of
WHAT was done.
+5
View File
@@ -0,0 +1,5 @@
---
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.
+31
View File
@@ -14,3 +14,34 @@
## Debugging
- To test opencode in the `packages/opencode` directory you can run `bun dev`
## Tool Calling
- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. Here is an example illustrating how to execute 3 parallel file reads in this chat environnement:
json
{
"recipient_name": "multi_tool_use.parallel",
"parameters": {
"tool_uses": [
{
"recipient_name": "functions.read",
"parameters": {
"filePath": "path/to/file.tsx"
}
},
{
"recipient_name": "functions.read",
"parameters": {
"filePath": "path/to/file.ts"
}
},
{
"recipient_name": "functions.read",
"parameters": {
"filePath": "path/to/file.md"
}
}
]
}
}
+72
View File
@@ -0,0 +1,72 @@
# Contributing to OpenCode
We want to make it easy for you to contribute to OpenCode. Here are the most common type of changes that get merged:
- Bug fixes
- Additional LSPs / Formatters
- Improvements to LLM performance
- Support for new providers
- Fixes for environment-specific quirks
- Missing standard behavior
- Documentation improvements
However, any UI or core product feature must go through a design review with the core team before implementation.
> [!IMPORTANT]
> We do not accept PRs for core features.
Take a look at recent git history to understand what usually lands.
If you are unsure if a PR would be accepted, feel free to ask a maintainer or look for issues with any of the following labels:
- [`help wanted`](https://github.com/sst/opencode/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelp-wanted)
- [`good first issue`](https://github.com/sst/opencode/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22)
- [`bug`](https://github.com/sst/opencode/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug)
> [!NOTE]
> PRs that ignore these guardrails will likely be closed.
Want to take on an issue? Leave a comment and a maintainer may assign it to you unless it is something we are already working on.
## Developing OpenCode
- Requirements: Bun 1.3+, Go 1.24.x.
- Install dependencies and start the dev server from the repo root:
```bash
bun install
bun dev
```
- Core pieces:
- `packages/opencode`: OpenCode core business logic & server.
- `packages/tui`: The TUI code, written in Go (will be removed soon in favor of [opentui](https://github.com/sst/opentui))
- `packages/plugin`: Source for `@opencode-ai/plugin`
> [!NOTE]
> After touching `packages/opencode/src/server/server.ts`, the OpenCode team must regenerate the Stainless SDK before any client updates merge.
## Pull Request Expectations
- Try to keep pull requests small and focused.
- Link relevant issue(s) in the description
- Explain the issue and why your change fixes it
- Avoid having verbose LLM generated PR descriptions
- Before adding new functions or functionality, ensure that such behavior doesn't already exist elsewhere in the codebase.
### Style Preferences
These are not strictly enforced, they are just general guidelines:
- **Functions:** Keep logic within a single function unless breaking it out adds clear reuse or composition benefits.
- **Destructuring:** Do not do unnecessary destructuring of variables.
- **Control flow:** Avoid `else` statements.
- **Error handling:** Prefer `.catch(...)` instead of `try`/`catch` when possible.
- **Types:** Reach for precise types and avoid `any`.
- **Variables:** Stick to immutable patterns and avoid `let`.
- **Naming:** Choose concise single-word identifiers when they remain descriptive.
- **Runtime APIs:** Use Bun helpers such as `Bun.file()` when they fit the use case.
## Feature Requests
For net-new functionality, start with a design conversation. Open an issue describing the problem, your proposed approach (optional), and why it belongs in OpenCode. The core team will help decide whether it should move forward; please wait for that approval instead of opening a feature PR directly.
+13 -44
View File
@@ -1,20 +1,20 @@
<p align="center">
<a href="https://opencode.ai">
<picture>
<source srcset="packages/web/src/assets/logo-ornate-dark.svg" media="(prefers-color-scheme: dark)">
<source srcset="packages/web/src/assets/logo-ornate-light.svg" media="(prefers-color-scheme: light)">
<img src="packages/web/src/assets/logo-ornate-light.svg" alt="opencode logo">
<source srcset="packages/console/app/src/asset/logo-ornate-dark.svg" media="(prefers-color-scheme: dark)">
<source srcset="packages/console/app/src/asset/logo-ornate-light.svg" media="(prefers-color-scheme: light)">
<img src="packages/console/app/src/asset/logo-ornate-light.svg" alt="OpenCode logo">
</picture>
</a>
</p>
<p align="center">AI coding agent, built for the terminal.</p>
<p align="center">The AI coding agent built for the terminal.</p>
<p align="center">
<a href="https://opencode.ai/discord"><img alt="Discord" src="https://img.shields.io/discord/1391832426048651334?style=flat-square&label=discord" /></a>
<a href="https://www.npmjs.com/package/opencode-ai"><img alt="npm" src="https://img.shields.io/npm/v/opencode-ai?style=flat-square" /></a>
<a href="https://github.com/sst/opencode/actions/workflows/publish.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/sst/opencode/publish.yml?style=flat-square&branch=dev" /></a>
</p>
[![opencode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai)
[![OpenCode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai)
---
@@ -26,6 +26,8 @@ curl -fsSL https://opencode.ai/install | bash
# Package managers
npm i -g opencode-ai@latest # or bun/pnpm/yarn
scoop bucket add extras; scoop install extras/opencode # Windows
winget install opencode # Windows
brew install sst/tap/opencode # macOS and Linux
paru -S opencode-bin # Arch Linux
```
@@ -50,45 +52,11 @@ XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash
### Documentation
For more info on how to configure opencode [**head over to our docs**](https://opencode.ai/docs).
For more info on how to configure OpenCode [**head over to our docs**](https://opencode.ai/docs).
### Contributing
opencode is an opinionated tool so any fundamental feature needs to go through a
design process with the core team.
> [!IMPORTANT]
> We do not accept PRs for core features.
However we still merge a ton of PRs - you can contribute:
- Bug fixes
- Improvements to LLM performance
- Support for new providers
- Fixes for env specific quirks
- Missing standard behavior
- Documentation
Take a look at the git history to see what kind of PRs we end up merging.
> [!NOTE]
> If you do not follow the above guidelines we might close your PR.
To run opencode locally you need.
- Bun
- Golang 1.24.x
And run.
```bash
$ bun install
$ bun dev
```
#### Development Notes
**API Client**: After making changes to the TypeScript API endpoints in `packages/opencode/src/server/server.ts`, you will need the opencode team to generate a new stainless sdk for the clients.
If you're interested in contributing to OpenCode, please read our [contributing docs](./CONTRIBUTING.md) before submitting a pull request.
### FAQ
@@ -97,9 +65,10 @@ $ bun dev
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.
- 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.
- 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.
- 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.
#### What's the other repo?
+115 -78
View File
@@ -1,80 +1,117 @@
# 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) |
| 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) |
+1654 -988
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

-2
View File
@@ -1,2 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z"/></svg>

Before

Width:  |  Height:  |  Size: 212 B

-2
View File
@@ -1,2 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><rect width="336" height="336" x="128" y="128" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32" rx="57" ry="57"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="m383.5 128l.5-24a56.16 56.16 0 0 0-56-56H112a64.19 64.19 0 0 0-64 64v216a56.16 56.16 0 0 0 56 56h24"/></svg>

Before

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 902 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 KiB

-19
View File
@@ -1,19 +0,0 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 16.5H24.5V33H8.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M48.5 16.5H64.5V33H48.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M120.5 16.5H136.5V33H120.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M160.5 16.5H176.5V33H160.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M192.5 16.5H208.5V33H192.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M232.5 16.5H248.5V33H232.5V16.5Z" fill="white" fill-opacity="0.2"/>
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="white" fill-opacity="0.95"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="white" fill-opacity="0.95"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="white" fill-opacity="0.5"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="white" fill-opacity="0.5"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="white" fill-opacity="0.95"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

-18
View File
@@ -1,18 +0,0 @@
<svg width="288" height="50" viewBox="0 0 288 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 16.5H24V33H8V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M48 16.5H64V33H48V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M120 16.5H136V33H120V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M160 16.5H176V33H160V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M192 16.5H208V33H192V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M232 16.5H248V33H232V16.5Z" fill="black" fill-opacity="0.15"/>
<path d="M264 0H288V8.5H272V16.5H288V25H272V33H288V41.5H264V0Z" fill="black" fill-opacity="0.95"/>
<path d="M248 0H224V41.5H248V33H232V8.5H248V0Z" fill="black" fill-opacity="0.95"/>
<path d="M256 8.5H248V33H256V8.5Z" fill="black" fill-opacity="0.95"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184 0H216V41.5H184V0ZM208 8.5H192V33H208V8.5Z" fill="black" fill-opacity="0.95"/>
<path d="M144 8.5H136V41.5H144V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M136 0H112V41.5H120V8.5H136V0Z" fill="black" fill-opacity="0.55"/>
<path d="M80 0H104V8.5H88V16.5H104V25H88V33H104V41.5H80V0Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40 0H72V41.5H48V49.5H40V0ZM64 8.5H48V33H64V8.5Z" fill="black" fill-opacity="0.55"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H32V41.5955H0V0ZM24 8.5H8V33H24V8.5Z" fill="black" fill-opacity="0.55"/>
<path d="M152 0H176V8.5H160V33H176V41.5H152V0Z" fill="black" fill-opacity="0.95"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

-12
View File
@@ -1,12 +0,0 @@
<svg width="289" height="50" viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="black"/>
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="black"/>
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z" fill="black"/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="black"/>
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="black"/>
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z" fill="black"/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 981 B

-71
View File
@@ -1,71 +0,0 @@
import { JSX } from "solid-js"
export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 289 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M264.5 0H288.5V8.5H272.5V16.5H288.5V25H272.5V33H288.5V41.5H264.5V0Z" fill="currentColor" />
<path d="M248.5 0H224.5V41.5H248.5V33H232.5V8.5H248.5V0Z" fill="currentColor" />
<path d="M256.5 8.5H248.5V33H256.5V8.5Z" fill="currentColor" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M184.5 0H216.5V41.5H184.5V0ZM208.5 8.5H192.5V33H208.5V8.5Z"
fill="currentColor"
/>
<path d="M144.5 8.5H136.5V41.5H144.5V8.5Z" fill="currentColor" />
<path d="M136.5 0H112.5V41.5H120.5V8.5H136.5V0Z" fill="currentColor" />
<path d="M80.5 0H104.5V8.5H88.5V16.5H104.5V25H88.5V33H104.5V41.5H80.5V0Z" fill="currentColor" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M40.5 0H72.5V41.5H48.5V49.5H40.5V0ZM64.5 8.5H48.5V33H64.5V8.5Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0.5 0H32.5V41.5955H0.5V0ZM24.5 8.5H8.5V33H24.5V8.5Z"
fill="currentColor"
/>
<path d="M152.5 0H176.5V8.5H160.5V33H176.5V41.5H152.5V0Z" fill="currentColor" />
</svg>
)
}
export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 512 512">
<rect
width="336"
height="336"
x="128"
y="128"
fill="none"
stroke="currentColor"
stroke-linejoin="round"
stroke-width="32"
rx="57"
ry="57"
></rect>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="32"
d="m383.5 128l.5-24a56.16 56.16 0 0 0-56-56H112a64.19 64.19 0 0 0-64 64v216a56.16 56.16 0 0 0 56 56h24"
></path>
</svg>
)
}
export function IconCheck(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg {...props} viewBox="0 0 24 24">
<path
fill="currentColor"
d="M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z"
></path>
</svg>
)
}
-13
View File
@@ -1,13 +0,0 @@
import { Account } from "@opencode/cloud-core/account.js"
import { redirect } from "@solidjs/router"
import type { APIEvent } from "@solidjs/start/server"
import { withActor } from "~/context/auth.withActor"
export async function GET(input: APIEvent) {
try {
const workspaces = await withActor(async () => Account.workspaces())
return redirect(`/workspace/${workspaces[0].id}`)
} catch {
return redirect("/auth/authorize")
}
}
-504
View File
@@ -1,504 +0,0 @@
[data-page="home"] {
--color-text: hsl(224, 10%, 10%);
--color-text-secondary: hsl(224, 7%, 46%);
--color-text-dimmed: hsl(224, 6%, 63%);
--color-text-inverted: hsl(0, 0%, 100%);
--color-border: hsl(224, 6%, 77%);
}
[data-page="home"] {
@media (prefers-color-scheme: dark) {
--color-text: hsl(0, 0%, 100%);
--color-text-secondary: hsl(224, 6%, 66%);
--color-text-dimmed: hsl(224, 7%, 46%);
--color-text-inverted: hsl(224, 10%, 10%);
--color-border: hsl(224, 6%, 36%);
}
}
[data-page="home"] {
--padding: 3rem;
--vertical-padding: 1.5rem;
--heading-font-size: 1.375rem;
@media (max-width: 30rem) {
--padding: 1rem;
--vertical-padding: 0.75rem;
--heading-font-size: 1rem;
}
display: flex;
gap: var(--vertical-padding);
flex-direction: column;
font-family: var(--font-mono);
color: var(--color-text);
padding: calc(var(--padding) + 1rem);
a {
color: var(--color-text);
text-decoration: underline;
text-underline-offset: var(--space-0-75);
text-decoration-thickness: 1px;
}
[data-component="content"] {
max-width: 67.5rem;
margin: 0 auto;
border: 1px solid var(--color-border);
}
[data-component="top"] {
padding: calc(var(--padding) * 1.5) var(--padding) var(--padding);
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: calc(var(--vertical-padding) / 2);
img {
height: auto;
width: clamp(200px, 85vw, 552px);
}
[data-slot="logo dark"] {
display: none;
}
@media (prefers-color-scheme: dark) {
[data-slot="logo light"] {
display: none;
}
[data-slot="logo dark"] {
display: block;
}
}
[data-slot="title"] {
line-height: 1.25;
font-weight: 500;
text-align: center;
font-size: var(--heading-font-size);
color: var(--color-text-secondary);
text-transform: uppercase;
}
[data-slot="login"] {
position: absolute;
top: 0;
right: 0;
border-width: 0 0 1px 1px;
border-style: solid;
border-color: var(--color-border);
background-color: var(--color-bg);
@media (max-width: 30rem) {
display: none;
}
a {
display: block;
padding: 0.5rem 1rem calc(0.5rem + 4px);
}
}
}
[data-component="cta"] {
border-top: 1px solid var(--color-border);
display: flex;
& > div + div {
border-left: 1px solid var(--color-border);
}
[data-slot="left"] {
flex: 0 0 auto;
text-align: center;
line-height: 1.4;
padding: var(--vertical-padding) 2rem;
text-transform: uppercase;
font-size: 1.125rem;
@media (max-width: 30rem) {
font-size: 1rem;
padding-bottom: calc(var(--vertical-padding) + 4px);
}
@media (max-width: 30rem) {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
}
[data-slot="center"] {
display: none;
@media (max-width: 30rem) {
display: block;
flex: 1;
text-align: center;
padding: var(--vertical-padding) 0.5rem;
border-top: 1px solid var(--color-border);
border-left: none;
}
}
[data-slot="right"] {
flex: 1;
padding: var(--vertical-padding) 1rem;
}
@media (max-width: 50rem) {
flex-direction: column;
[data-slot="right"] {
border-left: none;
border-top: 1px solid var(--color-border);
}
}
[data-slot="command"] {
all: unset;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--color-text-secondary);
font-size: 1.125rem;
font-family: var(--font-mono);
gap: var(--space-2);
width: 100%;
& > span {
@media (max-width: 24rem) {
font-size: 0.875rem;
}
@media (max-width: 56rem) {
[data-slot="protocol"] {
display: none;
}
}
@media (max-width: 38rem) {
text-align: center;
span:first-child {
display: block;
}
}
}
}
[data-slot="highlight"] {
color: var(--color-text);
font-weight: 500;
}
}
[data-component="features"] {
border-top: 1px solid var(--color-border);
padding: var(--padding);
[data-slot="list"] {
padding-left: var(--space-4);
margin: 0;
list-style: disc;
li {
margin-bottom: var(--space-4);
line-height: 1.6;
strong {
text-transform: uppercase;
font-weight: 600;
}
label {
line-height: 1;
text-transform: uppercase;
font-size: 0.75rem;
letter-spacing: 0.03125rem;
background: var(--color-border);
padding: 0.125rem 0.375rem;
color: var(--color-text-inverted);
}
}
li:last-child {
margin-bottom: 0;
}
}
}
[data-component="install"] {
border-top: 1px solid var(--color-border);
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
@media (max-width: 40rem) {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
[data-component="method"] {
display: flex;
padding: calc(var(--vertical-padding) / 2) calc(var(--padding) / 2) calc(var(--vertical-padding) / 2 + 0.125rem);
flex-direction: column;
text-align: left;
gap: var(--space-2-5);
@media (max-width: 30rem) {
gap: 0.3125rem;
}
@media (max-width: 40rem) {
text-align: left;
}
&:nth-child(2) {
border-left: 1px solid var(--color-border);
@media (max-width: 40rem) {
border-left: none;
border-top: 1px solid var(--color-border);
}
}
&:nth-child(3) {
border-top: 1px solid var(--color-border);
}
&:nth-child(4) {
border-top: 1px solid var(--color-border);
border-left: 1px solid var(--color-border);
@media (max-width: 40rem) {
border-left: none;
}
}
[data-component="title"] {
letter-spacing: -0.03125rem;
text-transform: uppercase;
font-weight: normal;
font-size: 1rem;
flex-shrink: 0;
color: var(--color-text-dimmed);
@media (max-width: 30rem) {
font-size: 0.75rem;
}
}
[data-slot="button"] {
all: unset;
cursor: pointer;
display: flex;
align-items: center;
color: var(--color-text-secondary);
gap: var(--space-2-5);
font-size: 1rem;
@media (max-width: 24rem) {
font-size: 0.875rem;
}
strong {
color: var(--color-text);
font-weight: 500;
}
@media (max-width: 40rem) {
justify-content: flex-start;
}
@media (max-width: 30rem) {
justify-content: center;
}
}
}
[data-component="screenshots"] {
border-top: 1px solid var(--color-border);
figure {
flex: 1;
display: flex;
flex-direction: column;
gap: calc(var(--padding) / 4);
padding: calc(var(--padding) / 2);
border-width: 0;
border-style: solid;
border-color: var(--color-border);
min-height: 0;
overflow: hidden;
& > div,
figcaption {
display: flex;
align-items: center;
}
& > div {
flex: 1;
min-height: 0;
display: flex;
align-items: center;
justify-content: center;
}
a {
display: flex;
flex: 1;
min-height: 0;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
figcaption {
letter-spacing: -0.03125rem;
text-transform: uppercase;
color: var(--color-text-dimmed);
flex-shrink: 0;
@media (max-width: 30rem) {
font-size: 0.75rem;
}
}
}
& > [data-slot="left"] figure {
height: var(--images-height);
box-sizing: border-box;
}
& > [data-slot="right"] figure {
height: calc(var(--images-height) / 2);
box-sizing: border-box;
}
& > [data-slot="left"] img {
width: 100%;
height: 100%;
min-width: 0;
object-fit: contain;
}
& > [data-slot="right"] img {
width: 100%;
height: calc(100% - 2rem);
object-fit: contain;
display: block;
}
@media (max-width: 30rem) {
& {
--images-height: auto;
grid-template-columns: 1fr;
grid-template-rows: auto auto;
}
& > [data-slot="left"] {
grid-row: 1;
grid-column: 1;
}
& > [data-slot="right"] {
grid-row: 2;
grid-column: 1;
border-left: none;
border-top: 1px solid var(--color-border);
& > [data-slot="row1"],
& > [data-slot="row2"] {
height: auto;
}
}
& > [data-slot="left"] figure,
& > [data-slot="right"] figure {
height: auto;
}
& > [data-slot="left"] img,
& > [data-slot="right"] img {
width: 100%;
height: auto;
max-height: none;
}
}
}
[data-component="copy-status"] {
@media (max-width: 38rem) {
display: none;
}
[data-slot="copy"] {
display: block;
width: var(--space-4);
height: var(--space-4);
color: var(--color-text-dimmed);
[data-copied] & {
display: none;
}
}
[data-slot="check"] {
display: none;
width: var(--space-4);
height: var(--space-4);
color: var(--color-text);
[data-copied] & {
display: block;
}
}
}
[data-component="footer"] {
border-top: 1px solid var(--color-border);
display: flex;
flex-direction: row;
[data-slot="cell"] {
flex: 1;
text-align: center;
text-transform: uppercase;
padding: var(--vertical-padding) 0.5rem;
}
[data-slot="cell"] + [data-slot="cell"] {
border-left: 1px solid var(--color-border);
}
/* Mobile: third column on its own row */
@media (max-width: 30rem) {
flex-wrap: wrap;
[data-slot="cell"]:nth-child(1),
[data-slot="cell"]:nth-child(2) {
flex: 1;
}
[data-slot="cell"]:nth-child(3) {
flex: 1 0 100%;
border-left: none;
border-top: 1px solid var(--color-border);
}
}
}
[data-component="legal"] {
color: var(--color-text-dimmed);
text-align: center;
a {
color: var(--color-text-dimmed);
}
}
}
-75
View File
@@ -1,75 +0,0 @@
import { Billing } from "@opencode/cloud-core/billing.js"
import type { APIEvent } from "@solidjs/start/server"
import { Database, eq, sql } from "@opencode/cloud-core/drizzle/index.js"
import { BillingTable, PaymentTable } from "@opencode/cloud-core/schema/billing.sql.js"
import { Identifier } from "@opencode/cloud-core/identifier.js"
import { centsToMicroCents } from "@opencode/cloud-core/util/price.js"
import { Actor } from "@opencode/cloud-core/actor.js"
import { Resource } from "@opencode/cloud-resource"
export async function POST(input: APIEvent) {
const body = await Billing.stripe().webhooks.constructEventAsync(
await input.request.text(),
input.request.headers.get("stripe-signature")!,
Resource.STRIPE_WEBHOOK_SECRET.value,
)
console.log(body.type, JSON.stringify(body, null, 2))
if (body.type === "checkout.session.completed") {
const workspaceID = body.data.object.metadata?.workspaceID
const customerID = body.data.object.customer as string
const paymentID = body.data.object.payment_intent as string
const amount = body.data.object.amount_total
if (!workspaceID) throw new Error("Workspace ID not found")
if (!customerID) throw new Error("Customer ID not found")
if (!amount) throw new Error("Amount not found")
if (!paymentID) throw new Error("Payment ID not found")
const chargedAmount = 2000
await Actor.provide("system", { workspaceID }, async () => {
const customer = await Billing.get()
if (customer?.customerID && customer.customerID !== customerID) throw new Error("Customer ID mismatch")
// set customer metadata
if (!customer?.customerID) {
await Billing.stripe().customers.update(customerID, {
metadata: {
workspaceID,
},
})
}
// get payment method for the payment intent
const paymentIntent = await Billing.stripe().paymentIntents.retrieve(paymentID, {
expand: ["payment_method"],
})
const paymentMethod = paymentIntent.payment_method
if (!paymentMethod || typeof paymentMethod === "string") throw new Error("Payment method not expanded")
await Database.transaction(async (tx) => {
await tx
.update(BillingTable)
.set({
balance: sql`${BillingTable.balance} + ${centsToMicroCents(chargedAmount)}`,
customerID,
paymentMethodID: paymentMethod.id,
paymentMethodLast4: paymentMethod.card!.last4,
})
.where(eq(BillingTable.workspaceID, workspaceID))
await tx.insert(PaymentTable).values({
workspaceID,
id: Identifier.create("payment"),
amount: centsToMicroCents(chargedAmount),
paymentID,
customerID,
})
})
})
}
console.log("finished handling")
return Response.json("ok", { status: 200 })
}
-67
View File
@@ -1,67 +0,0 @@
import "./workspace.css"
import { useAuthSession } from "~/context/auth.session"
import { IconLogo } from "../component/icon"
import { withActor } from "~/context/auth.withActor"
import {
query,
action,
redirect,
createAsync,
RouteSectionProps,
Navigate,
useNavigate,
useParams,
A,
} from "@solidjs/router"
import { User } from "@opencode/cloud-core/user.js"
import { Actor } from "@opencode/cloud-core/actor.js"
import { getRequestEvent } from "solid-js/web"
const getUserInfo = query(async (workspaceID: string) => {
"use server"
return withActor(async () => {
const actor = Actor.assert("user")
return await User.fromID(actor.properties.userID)
}, workspaceID)
}, "userInfo")
const logout = action(async () => {
"use server"
const auth = await useAuthSession()
const event = getRequestEvent()
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
})
throw redirect("/")
})
export default function WorkspaceLayout(props: RouteSectionProps) {
const params = useParams()
const userInfo = createAsync(() => getUserInfo(params.id))
return (
<main data-page="workspace">
<header data-component="workspace-header">
<div data-slot="header-brand">
<A href="/" data-component="site-title">
<IconLogo />
</A>
</div>
<div data-slot="header-actions">
<span data-slot="user">{userInfo()?.email}</span>
<form action={logout} method="post">
<button type="submit" formaction={logout}>
Logout
</button>
</form>
</div>
</header>
<div>{props.children}</div>
</main>
)
}
-630
View File
@@ -1,630 +0,0 @@
[data-page="workspace-[id]"] {
max-width: 64rem;
padding: var(--space-10) var(--space-4);
margin: 0 auto;
width: 100%;
display: flex;
flex-direction: column;
gap: var(--space-10);
@media (max-width: 30rem) {
padding-top: var(--space-4);
padding-bottom: var(--space-4);
gap: var(--space-8);
}
[data-slot="sections"] {
display: flex;
flex-direction: column;
gap: var(--space-16);
@media (max-width: 30rem) {
gap: var(--space-8);
}
section {
display: flex;
flex-direction: column;
gap: var(--space-6);
/* Section titles */
[data-slot="section-title"] {
display: flex;
flex-direction: column;
gap: var(--space-1);
h2 {
font-size: var(--font-size-md);
font-weight: 600;
line-height: 1.2;
letter-spacing: -0.03125rem;
margin: 0;
color: var(--color-text-secondary);
text-transform: uppercase;
@media (max-width: 30rem) {
font-size: var(--font-size-md);
}
}
}
}
section:not(:last-child) {
border-bottom: 1px solid var(--color-border);
padding-bottom: var(--space-16);
@media (max-width: 30rem) {
padding-bottom: var(--space-8);
}
}
}
[data-component="empty-state"] {
padding: var(--space-20) var(--space-6);
text-align: center;
border: 1px dashed var(--color-border);
border-radius: var(--border-radius-sm);
display: flex;
flex-direction: column;
gap: var(--space-2);
p {
line-height: 1.5;
font-size: var(--font-size-sm);
color: var(--color-text-muted);
}
}
/* Title section */
[data-component="title-section"] {
display: flex;
flex-direction: column;
gap: var(--space-2);
padding-bottom: var(--space-8);
border-bottom: 1px solid var(--color-border);
@media (max-width: 30rem) {
padding-bottom: var(--space-6);
}
h1 {
font-size: var(--font-size-2xl);
font-weight: 500;
line-height: 1.2;
letter-spacing: -0.03125rem;
margin: 0;
text-transform: uppercase;
@media (max-width: 30rem) {
font-size: var(--font-size-xl);
}
}
p {
line-height: 1.5;
font-size: var(--font-size-md);
color: var(--color-text-muted);
a {
color: var(--color-text-muted);
}
}
}
/* API Keys Section */
[data-component="api-keys-section"] {
[data-slot="create-form"] {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
[data-slot="input-container"] {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
@media (max-width: 30rem) {
gap: var(--space-2);
}
input {
flex: 1;
padding: var(--space-2) var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
background-color: var(--color-bg);
color: var(--color-text);
font-size: var(--font-size-sm);
font-family: var(--font-mono);
&:focus {
outline: none;
border-color: var(--color-accent);
}
&::placeholder {
color: var(--color-text-disabled);
}
}
[data-slot="form-actions"] {
display: flex;
gap: var(--space-2);
}
[data-slot="form-error"] {
color: var(--color-danger);
font-size: var(--font-size-sm);
margin-top: var(--space-1);
line-height: 1.4;
}
}
[data-slot="api-keys-table"] {
overflow-x: auto;
}
[data-slot="api-keys-table-element"] {
width: 100%;
border-collapse: collapse;
font-size: var(--font-size-sm);
thead {
border-bottom: 1px solid var(--color-border);
}
th {
padding: var(--space-3) var(--space-4);
text-align: left;
font-weight: normal;
color: var(--color-text-muted);
text-transform: uppercase;
}
td {
padding: var(--space-3) var(--space-4);
border-bottom: 1px solid var(--color-border-muted);
color: var(--color-text-muted);
font-family: var(--font-mono);
&[data-slot="key-name"] {
color: var(--color-text);
font-family: var(--font-sans);
font-weight: 500;
}
&[data-slot="key-value"] {
font-family: var(--font-mono);
button {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
font-size: var(--font-size-sm);
font-weight: 400;
border: none;
background-color: transparent;
color: var(--color-text-muted);
font-family: var(--font-mono);
border-radius: var(--border-radius-sm);
cursor: pointer;
transition: all 0.15s ease;
text-transform: none;
&:hover:not(:disabled) {
background-color: var(--color-bg-surface);
color: var(--color-text);
}
&:disabled {
cursor: default;
color: var(--color-text);
}
span {
font-family: inherit;
}
}
}
&[data-slot="key-date"] {
color: var(--color-text);
}
&[data-slot="key-actions"] {
font-family: var(--font-sans);
}
}
tbody tr {
&:last-child td {
border-bottom: none;
}
}
@media (max-width: 40rem) {
th,
td {
padding: var(--space-2) var(--space-3);
font-size: var(--font-size-xs);
}
th {
&:nth-child(3) /* Date */ {
display: none;
}
}
td {
&:nth-child(3) /* Date */ {
display: none;
}
}
}
}
}
/* Balance Section */
[data-component="balance-section"] {
[data-slot="balance"] {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
min-width: 14.5rem;
width: fit-content;
[data-slot="amount"] {
padding: var(--space-3-5) var(--space-4);
background-color: var(--color-bg-surface);
border-radius: var(--border-radius-sm);
display: flex;
align-items: baseline;
gap: var(--space-1);
justify-content: flex-end;
&[data-state="danger"] {
[data-slot="value"] {
color: var(--color-danger);
}
[data-slot="currency"] {
color: var(--color-danger);
}
}
[data-slot="currency"] {
position: relative;
bottom: 2px;
font-size: var(--font-size-lg);
color: var(--color-text-muted);
font-weight: 400;
}
[data-slot="value"] {
font-size: var(--font-size-3xl);
font-weight: 500;
color: var(--color-text);
}
}
}
}
/* Payments Section */
[data-component="payments-section"] {
[data-slot="payments-table"] {
overflow-x: auto;
}
[data-slot="payments-table-element"] {
width: 100%;
border-collapse: collapse;
font-size: var(--font-size-sm);
thead {
border-bottom: 1px solid var(--color-border);
}
th {
padding: var(--space-3) var(--space-4);
text-align: left;
font-weight: normal;
color: var(--color-text-muted);
text-transform: uppercase;
}
td {
padding: var(--space-3) var(--space-4);
border-bottom: 1px solid var(--color-border-muted);
color: var(--color-text-muted);
font-family: var(--font-mono);
&[data-slot="payment-date"] {
color: var(--color-text);
}
&[data-slot="payment-id"] {
font-family: var(--font-mono);
font-weight: 400;
color: var(--color-text-muted);
max-width: 200px;
word-break: break-word;
}
&[data-slot="payment-amount"] {
color: var(--color-text);
}
}
tbody tr {
&:last-child td {
border-bottom: none;
}
}
@media (max-width: 40rem) {
th,
td {
padding: var(--space-2) var(--space-3);
font-size: var(--font-size-xs);
}
th {
&:nth-child(2) /* Payment ID */ {
display: none;
}
}
td {
&:nth-child(2) /* Payment ID */ {
display: none;
}
}
}
}
}
/* Usage Section */
[data-component="usage-section"] {
[data-slot="usage-table"] {
overflow-x: auto;
}
[data-slot="usage-table-element"] {
width: 100%;
border-collapse: collapse;
font-size: var(--font-size-sm);
thead {
border-bottom: 1px solid var(--color-border);
}
th {
padding: var(--space-3) var(--space-4);
text-align: left;
font-weight: normal;
color: var(--color-text-muted);
text-transform: uppercase;
}
td {
padding: var(--space-3) var(--space-4);
border-bottom: 1px solid var(--color-border-muted);
color: var(--color-text-muted);
font-family: var(--font-mono);
&[data-slot="usage-date"] {
color: var(--color-text);
}
&[data-slot="usage-model"] {
font-family: var(--font-sans);
font-weight: 400;
color: var(--color-text-secondary);
max-width: 200px;
word-break: break-word;
}
&[data-slot="usage-cost"] {
color: var(--color-text);
}
}
tbody tr {
&:last-child td {
border-bottom: none;
}
}
@media (max-width: 40rem) {
th,
td {
padding: var(--space-2) var(--space-3);
font-size: var(--font-size-xs);
}
th {
&:nth-child(2) /* Model */ {
display: none;
}
}
td {
&:nth-child(2) /* Model */ {
display: none;
}
}
}
}
}
[data-slot="new-user-sections"] {
display: flex;
flex-direction: column;
gap: var(--space-8);
padding: var(--space-6);
background-color: var(--color-bg-surface);
border: 1px dashed var(--color-border);
border-radius: var(--border-radius-sm);
@media (max-width: 30rem) {
gap: var(--space-8);
padding: var(--space-4);
}
[data-component="feature-grid"] {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--space-6);
@media (max-width: 30rem) {
grid-template-columns: 1fr;
gap: var(--space-4);
}
[data-slot="feature"] {
display: flex;
flex-direction: column;
gap: var(--space-2);
padding: var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
h3 {
font-size: var(--font-size-sm);
font-weight: 600;
margin: 0;
color: var(--color-text);
text-transform: uppercase;
letter-spacing: -0.025rem;
}
p {
font-size: var(--font-size-sm);
line-height: 1.5;
margin: 0;
color: var(--color-text-muted);
}
}
}
[data-component="api-key-highlight"] {
display: flex;
flex-direction: column;
gap: var(--space-6);
[data-slot="section-title"] {
display: flex;
flex-direction: column;
gap: var(--space-1);
h2 {
font-size: var(--font-size-md);
font-weight: 600;
line-height: 1.2;
letter-spacing: -0.03125rem;
margin: 0;
color: var(--color-text-secondary);
text-transform: uppercase;
@media (max-width: 30rem) {
font-size: var(--font-size-md);
}
}
}
[data-slot="key-display"] {
display: flex;
flex-direction: column;
gap: var(--space-3);
[data-slot="key-container"] {
display: flex;
gap: var(--space-3);
padding: var(--space-4);
border: 2px solid var(--color-accent);
border-radius: var(--border-radius-sm);
align-items: center;
@media (max-width: 40rem) {
flex-direction: column;
gap: var(--space-3);
align-items: stretch;
}
[data-slot="key-value"] {
flex: 1;
font-family: var(--font-mono);
font-size: var(--font-size-sm);
color: var(--color-text);
background-color: var(--color-bg);
padding: var(--space-3);
border-radius: var(--border-radius-sm);
border: 1px solid var(--color-border);
word-break: break-all;
line-height: 1.4;
@media (max-width: 40rem) {
font-size: var(--font-size-xs);
padding: var(--space-2-5);
}
}
button {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
font-size: var(--font-size-sm);
font-weight: 500;
white-space: nowrap;
min-width: 130px;
@media (max-width: 40rem) {
justify-content: center;
padding: var(--space-2-5) var(--space-3);
font-size: var(--font-size-xs);
min-width: 96px;
}
}
}
}
}
[data-component="next-steps"] {
display: flex;
flex-direction: column;
gap: var(--space-6);
ol {
margin: 0;
padding-left: 0;
display: flex;
flex-direction: column;
gap: var(--space-2);
list-style-position: inside;
li {
font-size: var(--font-size-md);
line-height: 1.5;
color: var(--color-text-secondary);
code {
font-family: var(--font-mono);
font-size: var(--font-size-sm);
padding: var(--space-1) var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
color: var(--color-text);
}
}
}
}
}
}
-494
View File
@@ -1,494 +0,0 @@
import "./[id].css"
import { Billing } from "@opencode/cloud-core/billing.js"
import { Key } from "@opencode/cloud-core/key.js"
import { json, query, action, useParams, useAction, createAsync, useSubmission } from "@solidjs/router"
import { createEffect, createMemo, createSignal, For, Show } from "solid-js"
import { withActor } from "~/context/auth.withActor"
import { IconCopy, IconCheck } from "~/component/icon"
import { createStore } from "solid-js/store"
function formatDateForTable(date: Date) {
const options: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "short",
hour: "numeric",
minute: "2-digit",
hour12: true,
}
return date.toLocaleDateString("en-GB", options).replace(",", ",")
}
function formatDateUTC(date: Date) {
const options: Intl.DateTimeFormatOptions = {
weekday: "short",
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
second: "2-digit",
timeZoneName: "short",
timeZone: "UTC",
}
return date.toLocaleDateString("en-US", options)
}
/////////////////////////////////////
// Keys related queries and actions
/////////////////////////////////////
const listKeys = query(async (workspaceID: string) => {
"use server"
return withActor(() => Key.list(), workspaceID)
}, "key.list")
const createKey = action(async (form: FormData) => {
"use server"
const name = form.get("name")?.toString().trim()
if (!name) return { error: "Name is required" }
const workspaceID = form.get("workspaceID")?.toString()
if (!workspaceID) return { error: "Workspace ID is required" }
return json(
await withActor(
() =>
Key.create({ name })
.then((data) => ({ error: undefined, data }))
.catch((e) => ({ error: e.message as string })),
workspaceID,
),
{ revalidate: listKeys.key },
)
}, "key.create")
const removeKey = action(async (form: FormData) => {
"use server"
const id = form.get("id")?.toString()
if (!id) return { error: "ID is required" }
const workspaceID = form.get("workspaceID")?.toString()
if (!workspaceID) return { error: "Workspace ID is required" }
return json(await withActor(() => Key.remove({ id }), workspaceID), { revalidate: listKeys.key })
}, "key.remove")
/////////////////////////////////////
// Billing related queries and actions
/////////////////////////////////////
const getBalanceInfo = query(async (workspaceID: string) => {
"use server"
return withActor(async () => {
return await Billing.get()
}, workspaceID)
}, "balanceInfo")
const getUsageInfo = query(async (workspaceID: string) => {
"use server"
return withActor(async () => {
return await Billing.usages()
}, workspaceID)
}, "usageInfo")
const getPaymentsInfo = query(async (workspaceID: string) => {
"use server"
return withActor(async () => {
return await Billing.payments()
}, workspaceID)
}, "paymentsInfo")
const createCheckoutUrl = action(async (workspaceID: string, successUrl: string, cancelUrl: string) => {
"use server"
return withActor(() => Billing.generateCheckoutUrl({ successUrl, cancelUrl }), workspaceID)
}, "checkoutUrl")
// const createPortalUrl = action(async (workspaceID: string, returnUrl: string) => {
// "use server"
// return withActor(() => Billing.generatePortalUrl({ returnUrl }), workspaceID)
// }, "portalUrl")
function KeySection() {
const params = useParams()
const keys = createAsync(() => listKeys(params.id))
function formatKey(key: string) {
if (key.length <= 11) return key
return `${key.slice(0, 7)}...${key.slice(-4)}`
}
return (
<section data-component="api-keys-section">
<div data-slot="section-title">
<h2>API Keys</h2>
<p>Manage your API keys for accessing opencode services.</p>
</div>
<KeyCreateForm />
<div data-slot="api-keys-table">
<Show
when={keys()?.length}
fallback={
<div data-component="empty-state">
<p>Create an opencode Gateway API key</p>
</div>
}
>
<table data-slot="api-keys-table-element">
<thead>
<tr>
<th>Name</th>
<th>Key</th>
<th>Created</th>
<th></th>
</tr>
</thead>
<tbody>
<For each={keys()!}>
{(key) => {
const [copied, setCopied] = createSignal(false)
// const submission = useSubmission(removeKey, ([fd]) => fd.get("id")?.toString() === key.id)
return (
<tr>
<td data-slot="key-name">{key.name}</td>
<td data-slot="key-value">
<button
data-color="ghost"
disabled={copied()}
onClick={async () => {
await navigator.clipboard.writeText(key.key)
setCopied(true)
setTimeout(() => setCopied(false), 1000)
}}
title="Copy API key"
>
<span>{formatKey(key.key)}</span>
<Show when={copied()} fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}>
<IconCheck style={{ width: "14px", height: "14px" }} />
</Show>
</button>
</td>
<td data-slot="key-date" title={formatDateUTC(key.timeCreated)}>
{formatDateForTable(key.timeCreated)}
</td>
<td data-slot="key-actions">
<form action={removeKey} method="post">
<input type="hidden" name="id" value={key.id} />
<input type="hidden" name="workspaceID" value={params.id} />
<button data-color="ghost">Delete</button>
</form>
</td>
</tr>
)
}}
</For>
</tbody>
</table>
</Show>
</div>
</section>
)
}
function KeyCreateForm() {
const params = useParams()
const submission = useSubmission(createKey)
const [store, setStore] = createStore({ show: false })
let input: HTMLInputElement
createEffect(() => {
if (!submission.pending && submission.result && !submission.result.error) {
hide()
}
})
function show() {
// submission.clear() does not clear the result in some cases, ie.
// 1. Create key with empty name => error shows
// 2. Put in a key name and creates the key => form hides
// 3. Click add key button again => form shows with the same error if
// submission.clear() is called only once
while (true) {
submission.clear()
if (!submission.result) break
}
setStore("show", true)
input.focus()
}
function hide() {
setStore("show", false)
}
return (
<Show
when={store.show}
fallback={
<button data-color="primary" onClick={() => show()}>
Create API Key
</button>
}
>
<form action={createKey} method="post" data-slot="create-form">
<div data-slot="input-container">
<input ref={(r) => (input = r)} data-component="input" name="name" type="text" placeholder="Enter key name" />
<Show when={submission.result && submission.result.error}>
{(err) => <div data-slot="form-error">{err()}</div>}
</Show>
</div>
<input type="hidden" name="workspaceID" value={params.id} />
<div data-slot="form-actions">
<button type="reset" data-color="ghost" onClick={() => hide()}>
Cancel
</button>
<button type="submit" data-color="primary" disabled={submission.pending}>
{submission.pending ? "Creating..." : "Create"}
</button>
</div>
</form>
</Show>
)
}
function BalanceSection() {
const params = useParams()
const balanceInfo = createAsync(() => getBalanceInfo(params.id))
const createCheckoutUrlAction = useAction(createCheckoutUrl)
const createCheckoutUrlSubmission = useSubmission(createCheckoutUrl)
return (
<section data-component="balance-section">
<div data-slot="section-title">
<h2>Balance</h2>
<p>Add credits to your account.</p>
</div>
<div data-slot="balance">
<div
data-slot="amount"
data-state={(() => {
const balanceStr = ((balanceInfo()?.balance ?? 0) / 100000000).toFixed(2)
return balanceStr === "0.00" || balanceStr === "-0.00" ? "danger" : undefined
})()}
>
<span data-slot="currency">$</span>
<span data-slot="value">
{(() => {
const balanceStr = ((balanceInfo()?.balance ?? 0) / 100000000).toFixed(2)
return balanceStr === "-0.00" ? "0.00" : balanceStr
})()}
</span>
</div>
<button
data-color="primary"
disabled={createCheckoutUrlSubmission.pending}
onClick={async () => {
const baseUrl = window.location.href
const checkoutUrl = await createCheckoutUrlAction(params.id, baseUrl, baseUrl)
if (checkoutUrl) {
window.location.href = checkoutUrl
}
}}
>
{createCheckoutUrlSubmission.pending ? "Loading..." : "Buy Credits"}
</button>
</div>
</section>
)
}
function UsageSection() {
const params = useParams()
const usage = createAsync(() => getUsageInfo(params.id))
return (
<section data-component="usage-section">
<div data-slot="section-title">
<h2>Usage History</h2>
<p>Recent API usage and costs.</p>
</div>
<div data-slot="usage-table">
<Show
when={usage() && usage()!.length > 0}
fallback={
<div data-component="empty-state">
<p>Make your first API call to get started.</p>
</div>
}
>
<table data-slot="usage-table-element">
<thead>
<tr>
<th>Date</th>
<th>Model</th>
<th>Input</th>
<th>Output</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
<For each={usage()!}>
{(usage) => {
const date = createMemo(() => new Date(usage.timeCreated))
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-cost">${((usage.cost ?? 0) / 100000000).toFixed(4)}</td>
</tr>
)
}}
</For>
</tbody>
</table>
</Show>
</div>
</section>
)
}
function PaymentSection() {
const params = useParams()
const payments = createAsync(() => getPaymentsInfo(params.id))
return (
payments() &&
payments()!.length > 0 && (
<section data-component="payments-section">
<div data-slot="section-title">
<h2>Payments History</h2>
<p>Recent payment transactions.</p>
</div>
<div data-slot="payments-table">
<table data-slot="payments-table-element">
<thead>
<tr>
<th>Date</th>
<th>Payment ID</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<For each={payments()!}>
{(payment) => {
const date = new Date(payment.timeCreated)
return (
<tr>
<td data-slot="payment-date" title={formatDateUTC(date)}>
{formatDateForTable(date)}
</td>
<td data-slot="payment-id">{payment.id}</td>
<td data-slot="payment-amount">${((payment.amount ?? 0) / 100000000).toFixed(2)}</td>
</tr>
)
}}
</For>
</tbody>
</table>
</div>
</section>
)
)
}
function NewUserSection() {
const params = useParams()
const [copiedKey, setCopiedKey] = createSignal(false)
const keys = createAsync(() => listKeys(params.id))
const usage = createAsync(() => getUsageInfo(params.id))
const isNew = createMemo(() => {
const keysList = keys()
const usageList = usage()
return keysList?.length === 1 && (!usageList || usageList.length === 0)
})
const defaultKey = createMemo(() => keys()?.at(-1)?.key)
return (
<Show when={isNew()}>
<div data-slot="new-user-sections">
<div data-component="feature-grid">
<div data-slot="feature">
<h3>Tested & Verified Models</h3>
<p>We've benchmarked and tested models specifically for coding agents to ensure the best performance.</p>
</div>
<div data-slot="feature">
<h3>Highest Quality</h3>
<p>Access models configured for optimal performance - no downgrades or routing to cheaper providers.</p>
</div>
<div data-slot="feature">
<h3>No Lock-in</h3>
<p>Use Zen with any coding agent, and continue using other providers with opencode whenever you want.</p>
</div>
</div>
<div data-component="api-key-highlight">
<Show when={defaultKey()}>
<div data-slot="key-display">
<div data-slot="key-container">
<code data-slot="key-value">{defaultKey()}</code>
<button
data-color="primary"
disabled={copiedKey()}
onClick={async () => {
await navigator.clipboard.writeText(defaultKey() ?? "")
setCopiedKey(true)
setTimeout(() => setCopiedKey(false), 2000)
}}
title="Copy API key"
>
<Show
when={copiedKey()}
fallback={
<>
<IconCopy style={{ width: "16px", height: "16px" }} /> Copy Key
</>
}
>
<IconCheck style={{ width: "16px", height: "16px" }} /> Copied!
</Show>
</button>
</div>
</div>
</Show>
</div>
<div data-component="next-steps">
<ol>
<li>
Run <code>opencode auth login</code> and select opencode
</li>
<li>Paste your API key</li>
<li>Start opencode</li>
<li>
Run <code>/models</code> to see available models
</li>
</ol>
</div>
</div>
</Show>
)
}
export default function () {
return (
<div data-page="workspace-[id]">
<section data-component="title-section">
<h1>Zen</h1>
<p>
Curated list of models provided by opencode.{" "}
<a target="_blank" href="/docs/zen">
Learn more
</a>
.
</p>
</section>
<div data-slot="sections">
<NewUserSection />
<KeySection />
<BalanceSection />
<UsageSection />
<PaymentSection />
</div>
</div>
)
}
-9
View File
@@ -1,9 +0,0 @@
html {
line-height: 1;
background-color: var(--color-bg);
color: var(--color-text);
}
body {
font-family: var(--font-sans);
}
-531
View File
@@ -1,531 +0,0 @@
import type { APIEvent } from "@solidjs/start/server"
import path from "node:path"
import { and, Database, eq, isNull, sql } from "@opencode/cloud-core/drizzle/index.js"
import { KeyTable } from "@opencode/cloud-core/schema/key.sql.js"
import { BillingTable, UsageTable } from "@opencode/cloud-core/schema/billing.sql.js"
import { centsToMicroCents } from "@opencode/cloud-core/util/price.js"
import { Identifier } from "@opencode/cloud-core/identifier.js"
import { Resource } from "@opencode/cloud-resource"
type ModelCost = {
input: number
output: number
cacheRead?: number
cacheWrite5m?: number
cacheWrite1h?: number
}
type Model = {
id: string
auth: boolean
cost: ModelCost | ((usage: any) => ModelCost)
headerMappings: Record<string, string>
providers: Record<
string,
{
api: string
apiKey: string
model: string
weight?: number
}
>
}
export async function handler(
input: APIEvent,
opts: {
modifyBody?: (body: any) => any
setAuthHeader: (headers: Headers, apiKey: string) => void
parseApiKey: (headers: Headers) => string | undefined
onStreamPart: (chunk: string) => void
getStreamUsage: () => any
normalizeUsage: (body: any) => {
inputTokens: number
outputTokens: number
reasoningTokens?: number
cacheReadTokens?: number
cacheWrite5mTokens?: number
cacheWrite1hTokens?: number
}
},
) {
class AuthError extends Error {}
class CreditsError extends Error {}
class ModelError extends Error {}
const MODELS: Record<string, Model> = {
"claude-opus-4-1": {
id: "claude-opus-4-1" as const,
auth: true,
cost: {
input: 0.000015,
output: 0.000075,
cacheRead: 0.0000015,
cacheWrite5m: 0.00001875,
cacheWrite1h: 0.00003,
},
headerMappings: {},
providers: {
anthropic: {
api: "https://api.anthropic.com",
apiKey: Resource.ANTHROPIC_API_KEY.value,
model: "claude-opus-4-1-20250805",
},
},
},
"claude-sonnet-4": {
id: "claude-sonnet-4" as const,
auth: true,
cost: (usage: any) => {
const totalInputTokens =
usage.inputTokens + usage.cacheReadTokens + usage.cacheWrite5mTokens + usage.cacheWrite1hTokens
return totalInputTokens <= 200_000
? {
input: 0.000003,
output: 0.000015,
cacheRead: 0.0000003,
cacheWrite5m: 0.00000375,
cacheWrite1h: 0.000006,
}
: {
input: 0.000006,
output: 0.0000225,
cacheRead: 0.0000006,
cacheWrite5m: 0.0000075,
cacheWrite1h: 0.000012,
}
},
headerMappings: {},
providers: {
anthropic: {
api: "https://api.anthropic.com",
apiKey: Resource.ANTHROPIC_API_KEY.value,
model: "claude-sonnet-4-20250514",
},
},
},
"claude-3-5-haiku": {
id: "claude-3-5-haiku" as const,
auth: true,
cost: {
input: 0.0000008,
output: 0.000004,
cacheRead: 0.00000008,
cacheWrite5m: 0.000001,
cacheWrite1h: 0.0000016,
},
headerMappings: {},
providers: {
anthropic: {
api: "https://api.anthropic.com",
apiKey: Resource.ANTHROPIC_API_KEY.value,
model: "claude-3-5-haiku-20241022",
},
},
},
"gpt-5": {
id: "gpt-5" as const,
auth: true,
cost: {
input: 0.00000125,
output: 0.00001,
cacheRead: 0.000000125,
},
headerMappings: {},
providers: {
openai: {
api: "https://api.openai.com",
apiKey: Resource.OPENAI_API_KEY.value,
model: "gpt-5",
},
},
},
"qwen3-coder": {
id: "qwen3-coder" as const,
auth: true,
cost: {
input: 0.00000045,
output: 0.0000018,
},
headerMappings: {},
providers: {
baseten: {
api: "https://inference.baseten.co",
apiKey: Resource.BASETEN_API_KEY.value,
model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
weight: 4,
},
fireworks: {
api: "https://api.fireworks.ai/inference",
apiKey: Resource.FIREWORKS_API_KEY.value,
model: "accounts/fireworks/models/qwen3-coder-480b-a35b-instruct",
weight: 1,
},
},
},
"kimi-k2": {
id: "kimi-k2" as const,
auth: true,
cost: {
input: 0.0000006,
output: 0.0000025,
},
headerMappings: {},
providers: {
baseten: {
api: "https://inference.baseten.co",
apiKey: Resource.BASETEN_API_KEY.value,
model: "moonshotai/Kimi-K2-Instruct-0905",
weight: 4,
},
fireworks: {
api: "https://api.fireworks.ai/inference",
apiKey: Resource.FIREWORKS_API_KEY.value,
model: "accounts/fireworks/models/kimi-k2-instruct-0905",
weight: 1,
},
},
},
"grok-code": {
id: "grok-code" as const,
auth: false,
cost: {
input: 0,
output: 0,
cacheRead: 0,
},
headerMappings: {
"x-grok-conv-id": "x-opencode-session",
"x-grok-req-id": "x-opencode-request",
},
providers: {
xai: {
api: "https://api.x.ai",
apiKey: Resource.XAI_API_KEY.value,
model: "grok-code",
},
},
},
// deprecated
"qwen/qwen3-coder": {
id: "qwen/qwen3-coder" as const,
auth: true,
cost: {
input: 0.00000038,
output: 0.00000153,
},
headerMappings: {},
providers: {
baseten: {
api: "https://inference.baseten.co",
apiKey: Resource.BASETEN_API_KEY.value,
model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
weight: 5,
},
fireworks: {
api: "https://api.fireworks.ai/inference",
apiKey: Resource.FIREWORKS_API_KEY.value,
model: "accounts/fireworks/models/qwen3-coder-480b-a35b-instruct",
weight: 1,
},
},
},
}
const FREE_WORKSPACES = [
"wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank
]
const logger = {
metric: (values: Record<string, any>) => {
console.log(`_metric:${JSON.stringify(values)}`)
},
log: console.log,
debug: (message: string) => {
if (Resource.App.stage === "production") return
console.debug(message)
},
}
try {
const url = new URL(input.request.url)
const body = await input.request.json()
logger.debug(JSON.stringify(body))
logger.metric({
is_tream: !!body.stream,
session: input.request.headers.get("x-opencode-session"),
request: input.request.headers.get("x-opencode-request"),
})
const MODEL = validateModel()
const apiKey = await authenticate()
const isFree = FREE_WORKSPACES.includes(apiKey?.workspaceID ?? "")
await checkCredits()
const providerName = selectProvider()
const providerData = MODEL.providers[providerName]
logger.metric({ provider: providerName })
// Request to model provider
const startTimestamp = Date.now()
const res = await fetch(path.posix.join(providerData.api, url.pathname.replace(/^\/zen/, "") + url.search), {
method: "POST",
headers: (() => {
const headers = input.request.headers
headers.delete("host")
headers.delete("content-length")
opts.setAuthHeader(headers, providerData.apiKey)
Object.entries(MODEL.headerMappings ?? {}).forEach(([k, v]) => {
headers.set(k, headers.get(v)!)
})
return headers
})(),
body: JSON.stringify({
...(opts.modifyBody?.(body) ?? body),
model: providerData.model,
}),
})
// Scrub response headers
const resHeaders = new Headers()
const keepHeaders = ["content-type", "cache-control"]
for (const [k, v] of res.headers.entries()) {
if (keepHeaders.includes(k.toLowerCase())) {
resHeaders.set(k, v)
}
}
// Handle non-streaming response
if (!body.stream) {
const json = await res.json()
const body = JSON.stringify(json)
logger.metric({ response_length: body.length })
logger.debug(body)
await trackUsage(json.usage)
return new Response(body, {
status: res.status,
statusText: res.statusText,
headers: resHeaders,
})
}
// Handle streaming response
const stream = new ReadableStream({
start(c) {
const reader = res.body?.getReader()
const decoder = new TextDecoder()
let buffer = ""
let responseLength = 0
function pump(): Promise<void> {
return (
reader?.read().then(async ({ done, value }) => {
if (done) {
logger.metric({ response_length: responseLength })
const usage = opts.getStreamUsage()
if (usage) await trackUsage(usage)
c.close()
return
}
if (responseLength === 0) {
logger.metric({ time_to_first_byte: Date.now() - startTimestamp })
}
responseLength += value.length
buffer += decoder.decode(value, { stream: true })
const parts = buffer.split("\n\n")
buffer = parts.pop() ?? ""
for (const part of parts) {
logger.debug(part)
opts.onStreamPart(part.trim())
}
c.enqueue(value)
return pump()
}) || Promise.resolve()
)
}
return pump()
},
})
return new Response(stream, {
status: res.status,
statusText: res.statusText,
headers: resHeaders,
})
function validateModel() {
if (!(body.model in MODELS)) {
throw new ModelError(`Model ${body.model} not supported`)
}
const model = MODELS[body.model as keyof typeof MODELS]
logger.metric({ model: model.id })
return model
}
async function authenticate() {
try {
const apiKey = opts.parseApiKey(input.request.headers)
if (!apiKey) throw new AuthError("Missing API key.")
const key = await Database.use((tx) =>
tx
.select({
id: KeyTable.id,
workspaceID: KeyTable.workspaceID,
})
.from(KeyTable)
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
.then((rows) => rows[0]),
)
if (!key) throw new AuthError("Invalid API key.")
logger.metric({
api_key: key.id,
workspace: key.workspaceID,
})
return key
} catch (e) {
// ignore error if model does not require authentication
if (!MODEL.auth) return
throw e
}
}
async function checkCredits() {
if (!apiKey || !MODEL.auth || isFree) return
const billing = await Database.use((tx) =>
tx
.select({
balance: BillingTable.balance,
})
.from(BillingTable)
.where(eq(BillingTable.workspaceID, apiKey.workspaceID))
.then((rows) => rows[0]),
)
if (billing.balance <= 0) throw new CreditsError("Insufficient balance")
}
function selectProvider() {
const picks = Object.entries(MODEL.providers).flatMap(([name, provider]) =>
Array<string>(provider.weight ?? 1).fill(name),
)
return picks[Math.floor(Math.random() * picks.length)]
}
async function trackUsage(usage: any) {
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
opts.normalizeUsage(usage)
const modelCost = typeof MODEL.cost === "function" ? MODEL.cost(usage) : MODEL.cost
const inputCost = modelCost.input * inputTokens * 100
const outputCost = modelCost.output * outputTokens * 100
const reasoningCost = (() => {
if (!reasoningTokens) return undefined
return modelCost.output * reasoningTokens * 100
})()
const cacheReadCost = (() => {
if (!cacheReadTokens) return undefined
if (!modelCost.cacheRead) return undefined
return modelCost.cacheRead * cacheReadTokens * 100
})()
const cacheWrite5mCost = (() => {
if (!cacheWrite5mTokens) return undefined
if (!modelCost.cacheWrite5m) return undefined
return modelCost.cacheWrite5m * cacheWrite5mTokens * 100
})()
const cacheWrite1hCost = (() => {
if (!cacheWrite1hTokens) return undefined
if (!modelCost.cacheWrite1h) return undefined
return modelCost.cacheWrite1h * cacheWrite1hTokens * 100
})()
const totalCostInCent =
inputCost +
outputCost +
(reasoningCost ?? 0) +
(cacheReadCost ?? 0) +
(cacheWrite5mCost ?? 0) +
(cacheWrite1hCost ?? 0)
logger.metric({
"tokens.input": inputTokens,
"tokens.output": outputTokens,
"tokens.reasoning": reasoningTokens,
"tokens.cache_read": cacheReadTokens,
"tokens.cache_write_5m": cacheWrite5mTokens,
"tokens.cache_write_1h": cacheWrite1hTokens,
"cost.input": Math.round(inputCost),
"cost.output": Math.round(outputCost),
"cost.reasoning": reasoningCost ? Math.round(reasoningCost) : undefined,
"cost.cache_read": cacheReadCost ? Math.round(cacheReadCost) : undefined,
"cost.cache_write_5m": cacheWrite5mCost ? Math.round(cacheWrite5mCost) : undefined,
"cost.cache_write_1h": cacheWrite1hCost ? Math.round(cacheWrite1hCost) : undefined,
"cost.total": Math.round(totalCostInCent),
})
if (!apiKey) return
const cost = isFree ? 0 : centsToMicroCents(totalCostInCent)
await Database.transaction(async (tx) => {
await tx.insert(UsageTable).values({
workspaceID: apiKey.workspaceID,
id: Identifier.create("usage"),
model: MODEL.id,
provider: providerName,
inputTokens,
outputTokens,
reasoningTokens,
cacheReadTokens,
cacheWrite5mTokens,
cacheWrite1hTokens,
cost,
})
await tx
.update(BillingTable)
.set({
balance: sql`${BillingTable.balance} - ${cost}`,
})
.where(eq(BillingTable.workspaceID, apiKey.workspaceID))
})
await Database.use((tx) =>
tx
.update(KeyTable)
.set({ timeUsed: sql`now()` })
.where(eq(KeyTable.id, apiKey.id)),
)
}
} catch (error: any) {
logger.metric({
"error.type": error.constructor.name,
"error.message": error.message,
})
// Note: both top level "type" and "error.type" fields are used by the @ai-sdk/anthropic client to render the error message.
if (error instanceof AuthError || error instanceof CreditsError || error instanceof ModelError)
return new Response(
JSON.stringify({
type: "error",
error: { type: error.constructor.name, message: error.message },
}),
{ status: 401 },
)
return new Response(
JSON.stringify({
type: "error",
error: {
type: "error",
message: error.message,
},
}),
{ status: 500 },
)
}
}
-62
View File
@@ -1,62 +0,0 @@
{
"version": "7",
"dialect": "mysql",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1756796050935,
"tag": "0000_fluffy_raza",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1756871639102,
"tag": "0001_serious_whistler",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1757597611832,
"tag": "0002_violet_loners",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1757600397194,
"tag": "0003_dusty_clint_barton",
"breakpoints": true
},
{
"idx": 4,
"version": "5",
"when": 1757627357232,
"tag": "0004_first_mockingbird",
"breakpoints": true
},
{
"idx": 5,
"version": "5",
"when": 1757632304856,
"tag": "0005_jazzy_skrulls",
"breakpoints": true
},
{
"idx": 6,
"version": "5",
"when": 1757643108507,
"tag": "0006_parallel_gauntlet",
"breakpoints": true
},
{
"idx": 7,
"version": "5",
"when": 1757693869142,
"tag": "0007_familiar_nightshade",
"breakpoints": true
}
]
}
-29
View File
@@ -1,29 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode/cloud-core",
"version": "0.8.0",
"private": true,
"type": "module",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"@opencode/cloud-resource": "workspace:*",
"@planetscale/database": "1.19.0",
"drizzle-orm": "0.41.0",
"postgres": "3.4.7",
"stripe": "18.0.0",
"ulid": "3.0.0"
},
"exports": {
"./*": "./src/*"
},
"scripts": {
"db": "sst shell drizzle-kit",
"db-dev": "sst shell --stage dev -- drizzle-kit",
"db-prod": "sst shell --stage production -- drizzle-kit",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"drizzle-kit": "0.30.5",
"mysql2": "3.14.4"
}
}
-67
View File
@@ -1,67 +0,0 @@
import { z } from "zod"
import { and, eq, getTableColumns, isNull } from "drizzle-orm"
import { fn } from "./util/fn"
import { Database } from "./drizzle"
import { Identifier } from "./identifier"
import { AccountTable } from "./schema/account.sql"
import { Actor } from "./actor"
import { WorkspaceTable } from "./schema/workspace.sql"
import { UserTable } from "./schema/user.sql"
export namespace Account {
export const create = fn(
z.object({
email: z.string().email(),
id: z.string().optional(),
}),
async (input) =>
Database.transaction(async (tx) => {
const id = input.id ?? Identifier.create("account")
await tx.insert(AccountTable).values({
id,
email: input.email,
})
return id
}),
)
export const fromID = fn(z.string(), async (id) =>
Database.transaction(async (tx) => {
return tx
.select()
.from(AccountTable)
.where(eq(AccountTable.id, id))
.execute()
.then((rows) => rows[0])
}),
)
export const fromEmail = fn(z.string().email(), async (email) =>
Database.transaction(async (tx) => {
return tx
.select()
.from(AccountTable)
.where(eq(AccountTable.email, email))
.execute()
.then((rows) => rows[0])
}),
)
export const workspaces = async () => {
const actor = Actor.assert("account")
return Database.transaction(async (tx) =>
tx
.select(getTableColumns(WorkspaceTable))
.from(WorkspaceTable)
.innerJoin(UserTable, eq(UserTable.workspaceID, WorkspaceTable.id))
.where(
and(
eq(UserTable.email, actor.properties.email),
isNull(UserTable.timeDeleted),
isNull(WorkspaceTable.timeDeleted),
),
)
.execute(),
)
}
}
-120
View File
@@ -1,120 +0,0 @@
import { Stripe } from "stripe"
import { Database, eq, sql } from "./drizzle"
import { BillingTable, PaymentTable, UsageTable } from "./schema/billing.sql"
import { Actor } from "./actor"
import { fn } from "./util/fn"
import { z } from "zod"
import { User } from "./user"
import { Resource } from "@opencode/cloud-resource"
export namespace Billing {
export const stripe = () =>
new Stripe(Resource.STRIPE_SECRET_KEY.value, {
apiVersion: "2025-03-31.basil",
})
export const get = async () => {
return Database.use(async (tx) =>
tx
.select({
customerID: BillingTable.customerID,
paymentMethodID: BillingTable.paymentMethodID,
balance: BillingTable.balance,
reload: BillingTable.reload,
})
.from(BillingTable)
.where(eq(BillingTable.workspaceID, Actor.workspace()))
.then((r) => r[0]),
)
}
export const payments = async () => {
return await Database.use((tx) =>
tx
.select()
.from(PaymentTable)
.where(eq(PaymentTable.workspaceID, Actor.workspace()))
.orderBy(sql`${PaymentTable.timeCreated} DESC`)
.limit(100),
)
}
export const usages = async () => {
return await Database.use((tx) =>
tx
.select()
.from(UsageTable)
.where(eq(UsageTable.workspaceID, Actor.workspace()))
.orderBy(sql`${UsageTable.timeCreated} DESC`)
.limit(100),
)
}
export const generateCheckoutUrl = fn(
z.object({
successUrl: z.string(),
cancelUrl: z.string(),
}),
async (input) => {
const account = Actor.assert("user")
const { successUrl, cancelUrl } = input
const user = await User.fromID(account.properties.userID)
const customer = await Billing.get()
const session = await Billing.stripe().checkout.sessions.create({
mode: "payment",
line_items: [
{
price_data: {
currency: "usd",
product_data: {
name: "opencode credits",
},
unit_amount: 2123, // $20 minimum + Stripe fee 4.4% + $0.30
},
quantity: 1,
},
],
payment_intent_data: {
setup_future_usage: "on_session",
},
...(customer.customerID
? { customer: customer.customerID }
: {
customer_email: user.email,
customer_creation: "always",
}),
metadata: {
workspaceID: Actor.workspace(),
},
currency: "usd",
payment_method_types: ["card"],
success_url: successUrl,
cancel_url: cancelUrl,
})
return session.url
},
)
export const generatePortalUrl = fn(
z.object({
returnUrl: z.string(),
}),
async (input) => {
const { returnUrl } = input
const customer = await Billing.get()
if (!customer?.customerID) {
throw new Error("No stripe customer ID")
}
const session = await Billing.stripe().billingPortal.sessions.create({
customer: customer.customerID,
return_url: returnUrl,
})
return session.url
},
)
}
-75
View File
@@ -1,75 +0,0 @@
import { z } from "zod"
import { fn } from "./util/fn"
import { Actor } from "./actor"
import { and, Database, eq, isNull, sql } from "./drizzle"
import { Identifier } from "./identifier"
import { KeyTable } from "./schema/key.sql"
export namespace Key {
export const list = async () => {
const workspace = Actor.workspace()
const keys = await Database.use((tx) =>
tx
.select()
.from(KeyTable)
.where(and(eq(KeyTable.workspaceID, workspace), isNull(KeyTable.timeDeleted)))
.orderBy(sql`${KeyTable.timeCreated} DESC`),
)
return keys
}
export const create = fn(z.object({ name: z.string().min(1).max(255) }), async (input) => {
const workspaceID = Actor.workspace()
const { name } = input
// Generate secret key: sk- + 64 random characters (upper, lower, numbers)
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
let secretKey = "sk-"
const array = new Uint32Array(64)
crypto.getRandomValues(array)
for (let i = 0, l = array.length; i < l; i++) {
secretKey += chars[array[i] % chars.length]
}
const keyID = Identifier.create("key")
await Database.use((tx) =>
tx.insert(KeyTable).values({
id: keyID,
workspaceID,
actor: Actor.use(),
name,
key: secretKey,
timeUsed: null,
}),
).catch((e: any) => {
if (e.message.match(/Duplicate entry '.*' for key 'key.name'/))
throw new Error("A key with this name already exists. Please choose a different name.")
throw e
})
return keyID
})
export const remove = fn(z.object({ id: z.string() }), async (input) => {
const workspace = Actor.workspace()
await Database.transaction(async (tx) => {
const row = await tx
.select({
name: KeyTable.name,
})
.from(KeyTable)
.where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace)))
.then((rows) => rows[0])
if (!row) return
await tx
.update(KeyTable)
.set({
timeDeleted: sql`now()`,
oldName: row.name,
name: input.id, // Use the key ID as the name
})
.where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace)))
})
})
}
-12
View File
@@ -1,12 +0,0 @@
import { mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
import { id, timestamps } from "../drizzle/types"
export const AccountTable = mysqlTable(
"account",
{
id: id(),
...timestamps,
email: varchar("email", { length: 255 }).notNull(),
},
(table) => [uniqueIndex("email").on(table.email)],
)
-22
View File
@@ -1,22 +0,0 @@
import { mysqlTable, varchar, uniqueIndex, json } from "drizzle-orm/mysql-core"
import { timestamps, utc, workspaceColumns } from "../drizzle/types"
import { workspaceIndexes } from "./workspace.sql"
import { Actor } from "../actor"
export const KeyTable = mysqlTable(
"key",
{
...workspaceColumns,
...timestamps,
actor: json("actor").$type<Actor.Info>(),
name: varchar("name", { length: 255 }).notNull(),
oldName: varchar("old_name", { length: 255 }),
key: varchar("key", { length: 255 }).notNull(),
timeUsed: utc("time_used"),
},
(table) => [
...workspaceIndexes(table),
uniqueIndex("global_key").on(table.key),
uniqueIndex("name").on(table.workspaceID, table.name),
],
)
-16
View File
@@ -1,16 +0,0 @@
import { text, mysqlTable, uniqueIndex, varchar, int } from "drizzle-orm/mysql-core"
import { timestamps, utc, workspaceColumns } from "../drizzle/types"
import { workspaceIndexes } from "./workspace.sql"
export const UserTable = mysqlTable(
"user",
{
...workspaceColumns,
...timestamps,
email: varchar("email", { length: 255 }).notNull(),
name: varchar("name", { length: 255 }).notNull(),
timeSeen: utc("time_seen"),
color: int("color"),
},
(table) => [...workspaceIndexes(table), uniqueIndex("user_email").on(table.workspaceID, table.email)],
)
-18
View File
@@ -1,18 +0,0 @@
import { z } from "zod"
import { eq } from "drizzle-orm"
import { fn } from "./util/fn"
import { Database } from "./drizzle"
import { UserTable } from "./schema/user.sql"
export namespace User {
export const fromID = fn(z.string(), async (id) =>
Database.transaction(async (tx) => {
return tx
.select()
.from(UserTable)
.where(eq(UserTable.id, id))
.execute()
.then((rows) => rows[0])
}),
)
}
-58
View File
@@ -1,58 +0,0 @@
import { z } from "zod"
import { fn } from "./util/fn"
import { centsToMicroCents } from "./util/price"
import { Actor } from "./actor"
import { Database, eq } from "./drizzle"
import { Identifier } from "./identifier"
import { UserTable } from "./schema/user.sql"
import { BillingTable } from "./schema/billing.sql"
import { WorkspaceTable } from "./schema/workspace.sql"
import { Key } from "./key"
export namespace Workspace {
export const create = fn(z.void(), async () => {
const account = Actor.assert("account")
const workspaceID = Identifier.create("workspace")
await Database.transaction(async (tx) => {
await tx.insert(WorkspaceTable).values({
id: workspaceID,
})
await tx.insert(UserTable).values({
workspaceID,
id: Identifier.create("user"),
email: account.properties.email,
name: "",
})
await tx.insert(BillingTable).values({
workspaceID,
id: Identifier.create("billing"),
balance: 0,
})
})
await Actor.provide(
"system",
{
workspaceID,
},
async () => {
await Key.create({ name: "Default API Key" })
},
)
return workspaceID
})
export async function list() {
const account = Actor.assert("account")
return Database.use(async (tx) => {
return tx
.select({
id: WorkspaceTable.id,
slug: WorkspaceTable.slug,
name: WorkspaceTable.name,
})
.from(UserTable)
.innerJoin(WorkspaceTable, eq(UserTable.workspaceID, WorkspaceTable.id))
.where(eq(UserTable.email, account.properties.email))
})
}
}
-96
View File
@@ -1,96 +0,0 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/* deno-fmt-ignore-file */
import "sst"
declare module "sst" {
export interface Resource {
ANTHROPIC_API_KEY: {
type: "sst.sst.Secret"
value: string
}
AUTH_API_URL: {
type: "sst.sst.Linkable"
value: string
}
BASETEN_API_KEY: {
type: "sst.sst.Secret"
value: string
}
Console: {
type: "sst.cloudflare.SolidStart"
url: string
}
Database: {
database: string
host: string
password: string
port: number
type: "sst.sst.Linkable"
username: string
}
FIREWORKS_API_KEY: {
type: "sst.sst.Secret"
value: string
}
GITHUB_APP_ID: {
type: "sst.sst.Secret"
value: string
}
GITHUB_APP_PRIVATE_KEY: {
type: "sst.sst.Secret"
value: string
}
GITHUB_CLIENT_ID_CONSOLE: {
type: "sst.sst.Secret"
value: string
}
GITHUB_CLIENT_SECRET_CONSOLE: {
type: "sst.sst.Secret"
value: string
}
GOOGLE_CLIENT_ID: {
type: "sst.sst.Secret"
value: string
}
HONEYCOMB_API_KEY: {
type: "sst.sst.Secret"
value: string
}
OPENAI_API_KEY: {
type: "sst.sst.Secret"
value: string
}
STRIPE_SECRET_KEY: {
type: "sst.sst.Secret"
value: string
}
STRIPE_WEBHOOK_SECRET: {
type: "sst.sst.Linkable"
value: string
}
Web: {
type: "sst.cloudflare.Astro"
url: string
}
XAI_API_KEY: {
type: "sst.sst.Secret"
value: string
}
}
}
// cloudflare
import * as cloudflare from "@cloudflare/workers-types"
declare module "sst" {
export interface Resource {
Api: cloudflare.Service
AuthApi: cloudflare.Service
AuthStorage: cloudflare.KVNamespace
Bucket: cloudflare.R2Bucket
LogProcessor: cloudflare.Service
}
}
import "sst"
export {}
-96
View File
@@ -1,96 +0,0 @@
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
/* deno-fmt-ignore-file */
import "sst"
declare module "sst" {
export interface Resource {
ANTHROPIC_API_KEY: {
type: "sst.sst.Secret"
value: string
}
AUTH_API_URL: {
type: "sst.sst.Linkable"
value: string
}
BASETEN_API_KEY: {
type: "sst.sst.Secret"
value: string
}
Console: {
type: "sst.cloudflare.SolidStart"
url: string
}
Database: {
database: string
host: string
password: string
port: number
type: "sst.sst.Linkable"
username: string
}
FIREWORKS_API_KEY: {
type: "sst.sst.Secret"
value: string
}
GITHUB_APP_ID: {
type: "sst.sst.Secret"
value: string
}
GITHUB_APP_PRIVATE_KEY: {
type: "sst.sst.Secret"
value: string
}
GITHUB_CLIENT_ID_CONSOLE: {
type: "sst.sst.Secret"
value: string
}
GITHUB_CLIENT_SECRET_CONSOLE: {
type: "sst.sst.Secret"
value: string
}
GOOGLE_CLIENT_ID: {
type: "sst.sst.Secret"
value: string
}
HONEYCOMB_API_KEY: {
type: "sst.sst.Secret"
value: string
}
OPENAI_API_KEY: {
type: "sst.sst.Secret"
value: string
}
STRIPE_SECRET_KEY: {
type: "sst.sst.Secret"
value: string
}
STRIPE_WEBHOOK_SECRET: {
type: "sst.sst.Linkable"
value: string
}
Web: {
type: "sst.cloudflare.Astro"
url: string
}
XAI_API_KEY: {
type: "sst.sst.Secret"
value: string
}
}
}
// cloudflare
import * as cloudflare from "@cloudflare/workers-types"
declare module "sst" {
export interface Resource {
Api: cloudflare.Service
AuthApi: cloudflare.Service
AuthStorage: cloudflare.KVNamespace
Bucket: cloudflare.R2Bucket
LogProcessor: cloudflare.Service
}
}
import "sst"
export {}
-1
View File
@@ -1 +0,0 @@
src/scrap.ts
-20
View File
@@ -1,20 +0,0 @@
{
"name": "@opencode/cloud-scripts",
"version": "0.8.0",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"scripts": {
"shell": "sst shell -- bun tsx",
"shell-dev": "sst shell --stage dev -- bun tsx",
"shell-prod": "sst shell --stage production -- bun tsx"
},
"dependencies": {
"@opencode/cloud-core": "workspace:*",
"tsx": "4.20.5"
},
"devDependencies": {
"@types/node": "catalog:",
"typescript": "catalog:"
}
}
@@ -1,10 +0,0 @@
import { Database, eq } from "@opencode/cloud-core/drizzle/index.js"
import { UsageTable } from "@opencode/cloud-core/schema/billing.sql.js"
await Database.use(async (tx) => {
await tx
.update(UsageTable)
.set({ model: "grok-code" })
.where(eq(UsageTable.model, "x-ai/grok-code-fast-1"))
.limit(90000)
})
-9
View File
@@ -1,9 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node22/tsconfig.json",
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"types": ["@cloudflare/workers-types", "node"]
}
}
+4 -18
View File
@@ -6,15 +6,11 @@ branding:
inputs:
model:
description: "The model to use with opencode. Takes the format of `provider/model`."
description: "Model to use"
required: true
share:
description: "Whether to share the opencode session. Defaults to true for public repositories."
required: false
token:
description: "Optional GitHub access token for performing operations such as creating comments, committing changes, and opening pull requests. Defaults to the installation access token from the opencode GitHub App."
description: "Share the opencode session (defaults to true for public repos)"
required: false
runs:
@@ -24,20 +20,10 @@ runs:
shell: bash
run: curl -fsSL https://opencode.ai/install | bash
- name: Install bun
shell: bash
run: npm install -g bun
- name: Install dependencies
shell: bash
run: |
cd ${GITHUB_ACTION_PATH}
bun install
- name: Run opencode
shell: bash
run: bun ${GITHUB_ACTION_PATH}/index.ts
id: run_opencode
run: opencode github run
env:
MODEL: ${{ inputs.model }}
SHARE: ${{ inputs.share }}
TOKEN: ${{ inputs.token }}
+1 -1
View File
@@ -14,6 +14,6 @@
"@actions/github": "6.0.1",
"@octokit/graphql": "9.0.1",
"@octokit/rest": "22.0.0",
"@opencode-ai/sdk": "0.5.4"
"@opencode-ai/sdk": "workspace:*"
}
}
+1 -1
View File
@@ -6,4 +6,4 @@
/// <reference path="../sst-env.d.ts" />
import "sst"
export {}
export {}
+3 -1
View File
@@ -2,6 +2,8 @@ import { domain } from "./stage"
const GITHUB_APP_ID = new sst.Secret("GITHUB_APP_ID")
const GITHUB_APP_PRIVATE_KEY = new sst.Secret("GITHUB_APP_PRIVATE_KEY")
export const EMAILOCTOPUS_API_KEY = new sst.Secret("EMAILOCTOPUS_API_KEY")
const ADMIN_SECRET = new sst.Secret("ADMIN_SECRET")
const bucket = new sst.cloudflare.Bucket("Bucket")
export const api = new sst.cloudflare.Worker("Api", {
@@ -11,7 +13,7 @@ export const api = new sst.cloudflare.Worker("Api", {
WEB_DOMAIN: domain,
},
url: true,
link: [bucket, GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY],
link: [bucket, GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, ADMIN_SECRET],
transform: {
worker: (args) => {
args.logpush = true
+15 -19
View File
@@ -1,5 +1,5 @@
import { WebhookEndpoint } from "pulumi-stripe"
import { domain } from "./stage"
import { EMAILOCTOPUS_API_KEY } from "./app"
////////////////
// DATABASE
@@ -44,7 +44,7 @@ new sst.x.DevCommand("Studio", {
link: [database],
dev: {
command: "bun db studio",
directory: "cloud/core",
directory: "packages/console/core",
autostart: true,
},
})
@@ -59,7 +59,7 @@ const GOOGLE_CLIENT_ID = new sst.Secret("GOOGLE_CLIENT_ID")
const authStorage = new sst.cloudflare.Kv("AuthStorage")
export const auth = new sst.cloudflare.Worker("AuthApi", {
domain: `auth.${domain}`,
handler: "cloud/function/src/auth.ts",
handler: "packages/console/function/src/auth.ts",
url: true,
link: [database, authStorage, GITHUB_CLIENT_ID_CONSOLE, GITHUB_CLIENT_SECRET_CONSOLE, GOOGLE_CLIENT_ID],
})
@@ -68,13 +68,14 @@ export const auth = new sst.cloudflare.Worker("AuthApi", {
// GATEWAY
////////////////
export const stripeWebhook = new WebhookEndpoint("StripeWebhookEndpoint", {
export const stripeWebhook = new stripe.WebhookEndpoint("StripeWebhookEndpoint", {
url: $interpolate`https://${domain}/stripe/webhook`,
enabledEvents: [
"checkout.session.async_payment_failed",
"checkout.session.async_payment_succeeded",
"checkout.session.completed",
"checkout.session.expired",
"charge.refunded",
"customer.created",
"customer.deleted",
"customer.updated",
@@ -93,17 +94,10 @@ export const stripeWebhook = new WebhookEndpoint("StripeWebhookEndpoint", {
"customer.subscription.resumed",
"customer.subscription.trial_will_end",
"customer.subscription.updated",
"customer.tax_id.created",
"customer.tax_id.deleted",
"customer.tax_id.updated",
],
})
const ANTHROPIC_API_KEY = new sst.Secret("ANTHROPIC_API_KEY")
const OPENAI_API_KEY = new sst.Secret("OPENAI_API_KEY")
const XAI_API_KEY = new sst.Secret("XAI_API_KEY")
const BASETEN_API_KEY = new sst.Secret("BASETEN_API_KEY")
const FIREWORKS_API_KEY = new sst.Secret("FIREWORKS_API_KEY")
const ZEN_MODELS = new sst.Secret("ZEN_MODELS")
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!) },
@@ -116,28 +110,30 @@ const STRIPE_WEBHOOK_SECRET = new sst.Linkable("STRIPE_WEBHOOK_SECRET", {
// CONSOLE
////////////////
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")
let logProcessor
if ($app.stage === "production" || $app.stage === "frank") {
const HONEYCOMB_API_KEY = new sst.Secret("HONEYCOMB_API_KEY")
logProcessor = new sst.cloudflare.Worker("LogProcessor", {
handler: "cloud/function/src/log-processor.ts",
handler: "packages/console/function/src/log-processor.ts",
link: [HONEYCOMB_API_KEY],
})
}
new sst.cloudflare.x.SolidStart("Console", {
domain,
path: "cloud/app",
path: "packages/console/app",
link: [
database,
AUTH_API_URL,
STRIPE_WEBHOOK_SECRET,
STRIPE_SECRET_KEY,
ANTHROPIC_API_KEY,
OPENAI_API_KEY,
XAI_API_KEY,
BASETEN_API_KEY,
FIREWORKS_API_KEY,
ZEN_MODELS,
EMAILOCTOPUS_API_KEY,
AWS_SES_ACCESS_KEY_ID,
AWS_SES_SECRET_ACCESS_KEY,
],
environment: {
//VITE_DOCS_URL: web.url.apply((url) => url!),
+10
View File
@@ -0,0 +1,10 @@
import { domain } from "./stage"
new sst.cloudflare.StaticSite("Desktop", {
domain: "desktop." + domain,
path: "packages/desktop",
build: {
command: "bun turbo build",
output: "./dist",
},
})
+8
View File
@@ -3,3 +3,11 @@ export const domain = (() => {
if ($app.stage === "dev") return "dev.opencode.ai"
return `${$app.stage}.dev.opencode.ai`
})()
export const zoneID = "430ba34c138cfb5360826c4909f99be8"
new cloudflare.RegionalHostname("RegionalHostname", {
hostname: domain,
regionKey: "us",
zoneId: zoneID,
})
+2 -1
View File
@@ -46,7 +46,7 @@ mkdir -p "$INSTALL_DIR"
if [ -z "$requested_version" ]; then
url="https://github.com/sst/opencode/releases/latest/download/$filename"
specific_version=$(curl -s https://api.github.com/repos/sst/opencode/releases/latest | awk -F'"' '/"tag_name": "/ {gsub(/^v/, "", $4); print $4}')
specific_version=$(curl -s https://api.github.com/repos/sst/opencode/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
if [[ $? -ne 0 || -z "$specific_version" ]]; then
echo -e "${RED}Failed to fetch version information${NC}"
@@ -96,6 +96,7 @@ download_and_install() {
curl -# -L -o "$filename" "$url"
unzip -q "$filename"
mv opencode "$INSTALL_DIR"
chmod 755 "${INSTALL_DIR}/opencode"
cd .. && rm -rf opencodetmp
}
+1 -7
View File
@@ -1,9 +1,3 @@
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"weather": {
"type": "local",
"command": ["opencode", "x", "@h1deya/mcp-server-weather"]
}
}
"$schema": "https://opencode.ai/config.json"
}
+38 -18
View File
@@ -3,38 +3,57 @@
"name": "opencode",
"private": true,
"type": "module",
"packageManager": "bun@1.2.21",
"packageManager": "bun@1.3.0",
"scripts": {
"dev": "bun run --conditions=development packages/opencode/src/index.ts",
"typecheck": "bun run --filter='*' typecheck",
"generate": "(cd packages/sdk && ./js/script/generate.ts) && (cd packages/sdk/stainless && ./generate.ts)",
"postinstall": "./script/hooks"
"dev": "bun run packages/opencode/src/index.ts",
"typecheck": "bun turbo typecheck",
"prepare": "husky"
},
"workspaces": {
"packages": [
"cloud/*",
"packages/*",
"packages/sdk/js"
"packages/console/*",
"packages/sdk/js",
"packages/slack"
],
"catalog": {
"@types/bun": "1.2.21",
"@types/bun": "1.3.0",
"@hono/zod-validator": "0.4.2",
"@kobalte/core": "0.13.11",
"@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",
"@solidjs/meta": "0.29.4",
"@tailwindcss/vite": "4.1.11",
"diff": "8.0.2",
"ai": "5.0.8",
"hono": "4.7.10",
"fuzzysort": "3.1.0",
"luxon": "3.6.1",
"typescript": "5.8.2",
"zod": "3.25.76",
"@typescript/native-preview": "7.0.0-dev.20251014.1",
"zod": "4.1.8",
"remeda": "2.26.0",
"solid-js": "1.9.9"
"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"
}
},
"dependencies": {
"pulumi-stripe": "0.0.24"
},
"devDependencies": {
"prettier": "3.5.3",
"sst": "3.17.13"
"@tsconfig/bun": "catalog:",
"husky": "9.1.7",
"prettier": "3.6.2",
"sst": "3.17.19",
"turbo": "2.5.6"
},
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
"@opencode-ai/script": "workspace:*"
},
"repository": {
"type": "git",
@@ -53,10 +72,11 @@
"tree-sitter-bash",
"web-tree-sitter"
],
"overrides": {
"zod": "3.25.76"
},
"patchedDependencies": {
"@solidjs/start@1.1.7": "patches/@solidjs%2Fstart@1.1.7.patch"
},
"overrides": {
"@types/bun": "catalog:",
"@types/node": "catalog:"
}
}
@@ -1,23 +1,30 @@
{
"name": "@opencode/cloud-app",
"name": "@opencode-ai/console-app",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit",
"typecheck": "tsgo --noEmit",
"dev": "vinxi dev --host 0.0.0.0",
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
"build": "vinxi build && ../../packages/opencode/script/schema.ts ./.output/public/config.json",
"build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
"start": "vinxi start",
"version": "0.8.0"
"version": "0.15.12"
},
"dependencies": {
"@ibm/plex": "6.4.1",
"@kobalte/core": "catalog:",
"@openauthjs/openauth": "0.0.0-20250322224806",
"@opencode-ai/console-core": "workspace:*",
"@opencode-ai/console-resource": "workspace:*",
"@solidjs/meta": "^0.29.4",
"@solidjs/router": "^0.15.0",
"@solidjs/start": "^1.1.0",
"solid-js": "catalog:",
"vinxi": "^0.5.7",
"@opencode/cloud-core": "workspace:*"
"zod": "catalog:"
},
"devDependencies": {
"typescript": "catalog:",
"@typescript/native-preview": "catalog:"
},
"engines": {
"node": ">=22"
+1
View File
@@ -0,0 +1 @@
../../mail/emails/templates/static
@@ -0,0 +1,23 @@
<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>

After

Width:  |  Height:  |  Size: 1.6 KiB

+4
View File
@@ -0,0 +1,4 @@
<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>

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 14.3581L10.0541 17.7027L18 7" stroke="#8E8B8B" stroke-width="1.5" stroke-linecap="square"/>
</svg>

After

Width:  |  Height:  |  Size: 207 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z" stroke="#8E8B8B" stroke-width="1.5" stroke-linecap="square"/>
</svg>

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

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