Compare commits

...

274 Commits

Author SHA1 Message Date
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 Cline
5d95846df1 fix: openai reasoning issue (#2780) 2025-09-26 01:23:30 -04:00
Aiden Cline
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
Filip
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
Siddhant Choudhary
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
Alain Schlesser
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 Paris
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 Cline
c23510346b ignore: lsp debug file check (#2743) 2025-09-22 22:16:03 -05:00
Aiden Cline
f9c5df05a1 docs: github copilot model enable note (#2741) 2025-09-22 21:29:16 -05:00
Aiden Cline
02b4d1e2fc fix: lsp extension undefined handle (#2739) 2025-09-22 21:14:55 -05:00
Joseph Hanson
0b36eb8760 docs: fix permissions link (#2738) 2025-09-22 20:28:54 -05:00
Adam Hosker
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 Cline
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
iwauo
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 Cline
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 Cline
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
Osinachi Okpara
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 Cline
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 Cline
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
neriousy
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 Cline
ffa5689885 docs: subtask config option (#2682) 2025-09-18 17:52:23 -05:00
Aiden Cline
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 Clasen
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
Dax
65baf76df6 Plugin tool updates (#2670) 2025-09-18 04:26:57 -04:00
Dax
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 Quense
63c8874d2d fix: type exports in package.json for SDK package (#2654) 2025-09-17 23:39:26 -04:00
Julián Díaz
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 Cline
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 Cline
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 Clasen
16f9edc1a0 fix(TUI): display correct branch name in git worktree (#2626) 2025-09-17 09:46:18 -05:00
Aiden Cline
8c2aec43b8 fix: type 'reasoning' was provided without its required following item (#2633) 2025-09-17 09:45:13 -05:00
Aiden Cline
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 Cline
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
Mani Sundararajan
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
Dax
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 Murray
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
Dax
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
Dax
c1b4e1f19d Upgrade to Zod v4 (#2605)
Co-authored-by: GitHub Action <action@github.com>
2025-09-15 03:12:07 -04:00
Aiden Cline
89d820b1c4 fix: visual token bug (#2603) 2025-09-14 21:23:52 -05:00
Aiden Cline
e3e459fc50 fix: reasoning metadata persistence (#2602) 2025-09-14 16:28:06 -05:00
Tommy D. Rossi
4bf0541bd6 log bash output when using opencode run (#2595) 2025-09-14 09:03:40 -05:00
Aiden Cline
c81624aef7 tweak: make bash permissions key off of command pattern (#2592) 2025-09-14 09:01:57 -05:00
Kenn Costales
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
opencode
4b30705c42 release: v0.8.0 2025-09-14 06:07:43 +00:00
Mani Sundararajan
1f8d396b76 fix(dev): build tui with correct file ext for windows (#2590) 2025-09-14 01:59:25 -04:00
Aiden Cline
3752bb9717 fix: token counting visual bug (#2587) 2025-09-13 19:46:24 -05:00
Aiden Cline
16d66c209d respect subagent in command, add subtask flag (#2569) 2025-09-13 12:47:18 -05:00
Aiden Cline
6506e48c54 tweak: keep aborted msgs in context (#2583) 2025-09-13 12:25:30 -05:00
GitHub Action
f0e8b7c29b ignore: update download stats 2025-09-13 2025-09-13 12:03:56 +00:00
Dax Raad
a00b49d65b disable autocompact if context is 0 2025-09-13 05:59:18 -04:00
Dax Raad
b1589be4ba add disable OPENCODE_DISABLE_AUTOCOMPACT 2025-09-13 05:55:04 -04:00
Dax Raad
eb24d2f847 ignore: fix 2025-09-13 05:53:03 -04:00
Dax
9bb25a9260 Session management and prompt handling improvements (#2577)
Co-authored-by: GitHub Action <action@github.com>
2025-09-13 05:46:14 -04:00
opencode
535230dce4 release: v0.7.9 2025-09-13 05:29:37 +00:00
Dax Raad
555fb53505 nudge llm to continue properly after compaction 2025-09-13 01:23:54 -04:00
Tommy D. Rossi
b1e0a23351 fix: ShellError: exit code 1 errors (#2568)
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-13 00:06:07 -05:00
Nicholas Hamilton
2b69bcccdf docs: typo in web agents.mdx (#2574) 2025-09-12 23:26:52 -05:00
Trillium Smith
e03f27381f docs: add tip block for finding available models (#2501)
Co-authored-by: GitHub Action <action@github.com>
2025-09-12 21:22:54 -04:00
Aiden Cline
aebd50da7e fix: make permission always behavior match expectation (#2573) 2025-09-12 18:59:38 -05:00
Stephen Murray
c02f58c2af fix: await cleanupRevert() to prevent dupe msgs after undo (#2572) 2025-09-12 18:42:39 -05:00
Dax Raad
c8f4d54f7f wip: zen 2025-09-12 14:53:00 -04:00
GitHub Action
4983d255dd chore: format code 2025-09-12 18:46:43 +00:00
Dax Raad
f2b4891ff0 wip: zen 2025-09-12 14:46:08 -04:00
GitHub Action
efcb5abbf7 chore: format code 2025-09-12 18:33:14 +00:00
Jay V
d37e58719e ignore: zen 2025-09-12 14:32:43 -04:00
Frank
c6c153de95 wip: zen 2025-09-12 14:22:42 -04:00
opencode
417e8f619c release: v0.7.8 2025-09-12 18:09:55 +00:00
Dax Raad
f2094b7bb3 temporarily disable midstream compaction 2025-09-12 14:00:54 -04:00
Dax Raad
176dc51b2e ci: exclude production branch from format workflow 2025-09-12 13:41:38 -04:00
opencode
f7d9a031e6 release: v0.7.7 2025-09-12 17:28:35 +00:00
Dax Raad
3e2478ebf9 undo session pruning 2025-09-12 13:20:13 -04:00
GitHub Action
1f4e8b4954 chore: format code 2025-09-12 16:19:09 +00:00
Frank
9a346a00fb wip: zen 2025-09-12 12:18:32 -04:00
Frank
0a13820927 Merge branch 'production' into dev 2025-09-12 12:04:27 -04:00
GitHub Action
c5fa3ee9f8 chore: format code 2025-09-12 15:57:50 +00:00
Frank
c294a18155 wip: zen 2025-09-12 11:57:14 -04:00
Frank
c3dc6d6df6 wip: zen 2025-09-12 11:57:14 -04:00
GitHub Action
ef3425a177 ignore: update download stats 2025-09-12 2025-09-12 12:04:14 +00:00
Dax Raad
0290b4aaf0 ignore: internal 2025-09-12 10:45:44 +00:00
opencode
4ceee53480 release: v0.7.6 2025-09-12 10:45:44 +00:00
Dax Raad
469dc9095f add microcompact 2025-09-12 06:38:47 -04:00
opencode
661d50f95f release: v0.7.5 2025-09-12 10:25:57 +00:00
opencode
3978a8e636 release: v0.7.4 2025-09-12 10:08:33 +00:00
Dax Raad
983e3b2ee3 fix compaction issues 2025-09-12 06:01:11 -04:00
GitHub Action
1bd198eb34 chore: format code 2025-09-11 22:34:21 +00:00
GitHub Action
3c502861a7 chore: format code 2025-09-11 22:30:52 +00:00
Frank
a52b352b24 wip: zen 2025-09-11 18:30:13 -04:00
Dax Raad
79c73267cf wip: zen 2025-09-11 18:20:37 -04:00
opencode
54f7fb5019 release: v0.7.3 2025-09-11 21:38:17 +00:00
Frank
dd97d784b6 Merge branch 'production' into dev 2025-09-11 17:28:51 -04:00
GitHub Action
91832bd5d7 chore: format code 2025-09-11 21:22:56 +00:00
Frank
3abca8fd4b wip: zen 2025-09-11 17:22:05 -04:00
Dax Raad
f5b3992479 properly support model level npm definition 2025-09-11 16:22:44 -04:00
Chris Covington
53f1f16122 feat: Add an experimental option to disable paste summaries (#2552)
Co-authored-by: rekram1-node <aidenpcline@gmail.com>
2025-09-11 14:21:08 -05:00
Aiden Cline
4614e4983e fix: command being passed as arg when no args present (#2553) 2025-09-11 13:03:12 -05:00
GitHub Action
37b6a55eb1 chore: format code 2025-09-11 04:00:17 +00:00
1440 changed files with 40887 additions and 9445 deletions

View File

@@ -1,8 +1,12 @@
name: Format
name: format
on:
push:
branches-ignore:
- production
pull_request:
branches-ignore:
- production
workflow_dispatch:
jobs:
format:

50
.github/workflows/snapshot.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
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: 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-
- name: Install dependencies
run: bun install
- name: Publish
run: |
./packages/opencode/script/publish.ts
env:
OPENCODE_SNAPSHOT: true
OPENCODE_TAG: ${{ github.ref_name }}
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,4 +1,4 @@
name: Typecheck
name: typecheck
on:
pull_request:

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ node_modules
openapi.json
playground
tmp
dist
.turbo

3
.husky/pre-push Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
bun prettier --write --ignore-unknown $(git diff --name-only HEAD~1 HEAD)
bun run typecheck

View File

@@ -76,3 +76,17 @@
| 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) |

1661
bun.lock

File diff suppressed because it is too large Load Diff

View File

@@ -1,308 +0,0 @@
/**
* @deprecated Use zen/v1/chat/completions instead
*/
import { Resource } from "@opencode/cloud-resource"
import type { APIEvent } from "@solidjs/start/server"
import { Database, eq, 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"
const MODELS = {
// "anthropic/claude-sonnet-4": {
// auth: true,
// api: "https://api.anthropic.com",
// apiKey: Resource.ANTHROPIC_API_KEY.value,
// model: "claude-sonnet-4-20250514",
// cost: {
// input: 0.0000015,
// output: 0.000006,
// reasoning: 0.0000015,
// cacheRead: 0.0000001,
// cacheWrite: 0.0000001,
// },
// headerMappings: {},
// },
"qwen/qwen3-coder": {
id: "qwen/qwen3-coder",
auth: true,
api: "https://inference.baseten.co",
apiKey: Resource.BASETEN_API_KEY.value,
model: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
cost: {
input: 0.00000038,
output: 0.00000153,
reasoning: 0,
cacheRead: 0,
cacheWrite: 0,
},
headerMappings: {},
},
"grok-code": {
id: "x-ai/grok-code-fast-1",
auth: false,
api: "https://api.x.ai",
apiKey: Resource.XAI_API_KEY.value,
model: "grok-code",
cost: {
input: 0,
output: 0,
reasoning: 0,
cacheRead: 0,
cacheWrite: 0,
},
headerMappings: {
"x-grok-conv-id": "x-opencode-session",
"x-grok-req-id": "x-opencode-request",
},
},
}
class AuthError extends Error {}
class CreditsError extends Error {}
class ModelError extends Error {}
export async function POST(input: APIEvent) {
try {
const url = new URL(input.request.url)
const body = await input.request.json()
const MODEL = validateModel()
const apiKey = await authenticate()
await checkCredits()
// Request to model provider
const res = await fetch(new URL(url.pathname.replace(/^\/gateway/, "") + url.search, MODEL.api), {
method: "POST",
headers: (() => {
const headers = input.request.headers
headers.delete("host")
headers.delete("content-length")
headers.set("authorization", `Bearer ${MODEL.apiKey}`)
Object.entries(MODEL.headerMappings ?? {}).forEach(([k, v]) => {
headers.set(k, headers.get(v)!)
})
return headers
})(),
body: JSON.stringify({
...body,
model: MODEL.model,
stream_options: {
include_usage: true,
},
}),
})
// 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 body = await res.json()
await trackUsage(body)
return new Response(JSON.stringify(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 = ""
function pump(): Promise<void> {
return (
reader?.read().then(async ({ done, value }) => {
if (done) {
c.close()
return
}
buffer += decoder.decode(value, { stream: true })
const parts = buffer.split("\n\n")
buffer = parts.pop() ?? ""
const usage = parts
.map((part) => part.trim())
.filter((part) => part.startsWith("data: "))
.map((part) => {
try {
return JSON.parse(part.slice(6))
} catch (e) {
return {}
}
})
.find((part) => part.usage)
if (usage) await trackUsage(usage)
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`)
}
return MODELS[body.model as keyof typeof MODELS]
}
async function authenticate() {
try {
const authHeader = input.request.headers.get("authorization")
if (!authHeader || !authHeader.startsWith("Bearer ")) throw new AuthError("Missing API key.")
const apiKey = authHeader.split(" ")[1]
const key = await Database.use((tx) =>
tx
.select({
id: KeyTable.id,
workspaceID: KeyTable.workspaceID,
})
.from(KeyTable)
.where(eq(KeyTable.key, apiKey))
.then((rows) => rows[0]),
)
if (!key) throw new AuthError("Invalid API key.")
return key
} catch (e) {
console.log(e)
// ignore error if model does not require authentication
if (!MODEL.auth) return
throw e
}
}
async function checkCredits() {
if (!apiKey || !MODEL.auth) 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")
}
async function trackUsage(chunk: any) {
console.log(`trackUsage ${apiKey}`)
if (!apiKey) return
const usage = chunk.usage
const inputTokens = usage.prompt_tokens ?? 0
const outputTokens = usage.completion_tokens ?? 0
const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0
const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0
//const cacheWriteTokens = providerMetadata?.["anthropic"]?.["cacheCreationInputTokens"] ?? 0
const cacheWriteTokens = 0
const inputCost = MODEL.cost.input * inputTokens
const outputCost = MODEL.cost.output * outputTokens
const reasoningCost = MODEL.cost.reasoning * reasoningTokens
const cacheReadCost = MODEL.cost.cacheRead * cacheReadTokens
const cacheWriteCost = MODEL.cost.cacheWrite * cacheWriteTokens
const costInCents = (inputCost + outputCost + reasoningCost + cacheReadCost + cacheWriteCost) * 100
const cost = centsToMicroCents(costInCents)
await Database.transaction(async (tx) => {
await tx.insert(UsageTable).values({
workspaceID: apiKey.workspaceID,
id: Identifier.create("usage"),
model: MODEL.id,
inputTokens,
outputTokens,
reasoningTokens,
cacheReadTokens,
cacheWriteTokens,
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) {
if (error instanceof AuthError) {
return new Response(
JSON.stringify({
error: {
message: error.message,
type: "invalid_request_error",
param: null,
code: "unauthorized",
},
}),
{
status: 401,
},
)
}
if (error instanceof CreditsError) {
return new Response(
JSON.stringify({
error: {
message: error.message,
type: "insufficient_quota",
param: null,
code: "insufficient_quota",
},
}),
{
status: 401,
},
)
}
if (error instanceof ModelError) {
return new Response(JSON.stringify({ error: { message: error.message } }), {
status: 401,
})
}
console.log(error)
return new Response(JSON.stringify({ error: { message: error.message } }), {
status: 500,
})
}
}

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 })
}

View File

@@ -1,634 +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;
gap: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
@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="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-16);
@media (max-width: 30rem) {
gap: var(--space-8);
}
[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);
background-color: var(--color-bg-surface);
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);
background-color: var(--color-bg-surface);
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);
[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);
}
}
}
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-sm);
line-height: 1.5;
color: var(--color-text-muted);
code {
font-family: var(--font-mono);
font-size: var(--font-size-xs);
padding: var(--space-1) var(--space-2);
background-color: var(--color-bg-surface);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
color: var(--color-text);
}
}
}
}
}
}

View File

@@ -1,588 +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 { createMemo, createSignal, For, Show } from "solid-js"
import { withActor } from "~/context/auth.withActor"
import { IconCopy, IconCheck } from "~/component/icon"
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 (workspaceID: string, name: string) => {
"use server"
return json(
withActor(() => Key.create({ name }), workspaceID),
{ revalidate: listKeys.key },
)
}, "key.create")
const removeKey = action(async (workspaceID: string, id: string) => {
"use server"
return json(
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 KeysSection() {
// Dummy data for testing
const dummyKeys = [
{
id: "key_1",
name: "Development API Key",
key: "oc_dev_1234567890abcdef1234567890abcdef12345678",
timeCreated: new Date("2024-01-15T10:30:00Z"),
},
{
id: "key_2",
name: "Production API Key",
key: "oc_prod_abcdef1234567890abcdef1234567890abcdef12",
timeCreated: new Date("2024-02-01T14:22:00Z"),
},
{
id: "key_3",
name: "Testing Environment",
key: "oc_test_9876543210fedcba9876543210fedcba98765432",
timeCreated: new Date("2024-02-10T09:15:00Z"),
},
]
const params = useParams()
const keys = createAsync(() => listKeys(params.id))
// const keys = () => dummyKeys
const [showForm, setShowForm] = createSignal(false)
const [name, setName] = createSignal("")
const removeAction = useAction(removeKey)
const createAction = useAction(createKey)
const createSubmission = useSubmission(createKey)
const [copiedId, setCopiedId] = createSignal<string | null>(null)
function formatKey(key: string) {
if (key.length <= 11) return key
return `${key.slice(0, 7)}...${key.slice(-4)}`
}
async function handleCreateKey() {
if (!name().trim()) return
try {
await createAction(params.id, name().trim())
setName("")
setShowForm(false)
} catch (error) {
console.error("Failed to create API key:", error)
}
}
async function copyKeyToClipboard(text: string, keyId: string) {
try {
await navigator.clipboard.writeText(text)
setCopiedId(keyId)
setTimeout(() => setCopiedId(null), 1500)
} catch (error) {
console.error("Failed to copy to clipboard:", error)
}
}
async function handleDeleteKey(keyId: string) {
if (!confirm("Are you sure you want to delete this API key?")) {
return
}
try {
await removeAction(params.id, keyId)
} catch (error) {
console.error("Failed to delete API key:", error)
}
}
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>
<Show
when={!showForm()}
fallback={
<div data-slot="create-form">
<input
data-component="input"
type="text"
placeholder="Enter key name"
value={name()}
onInput={(e) => setName(e.currentTarget.value)}
onKeyPress={(e) => e.key === "Enter" && handleCreateKey()}
/>
<div data-slot="form-actions">
<button
data-color="ghost"
onClick={() => {
setShowForm(false)
setName("")
}}
>
Cancel
</button>
<button
data-color="primary"
disabled={createSubmission.pending || !name().trim()}
onClick={handleCreateKey}
>
{createSubmission.pending ? "Creating..." : "Create"}
</button>
</div>
</div>
}
>
<button
data-color="primary"
onClick={() => {
console.log("clicked")
setShowForm(true)
}}
>
Create API Key
</button>
</Show>
<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) => (
<tr>
<td data-slot="key-name">{key.name}</td>
<td data-slot="key-value">
<button
data-color="ghost"
disabled={copiedId() === key.id}
onClick={() => copyKeyToClipboard(key.key, key.id)}
title="Copy API key"
>
<span>{formatKey(key.key)}</span>
<Show
when={copiedId() === key.id}
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">
<button data-color="ghost" onClick={() => handleDeleteKey(key.id)} title="Delete API key">
Delete
</button>
</td>
</tr>
)}
</For>
</tbody>
</table>
</Show>
</div>
</section>
)
}
function BalanceSection() {
const params = useParams()
const dummyBalanceInfo = { balance: 2500000000 } // $25.00 in cents
const balanceInfo = createAsync(() => getBalanceInfo(params.id))
// const balanceInfo = () => dummyBalanceInfo
const createCheckoutUrlAction = useAction(createCheckoutUrl)
const createCheckoutUrlSubmission = useSubmission(createCheckoutUrl)
async function handleBuyCredits() {
try {
const baseUrl = window.location.href
const checkoutUrl = await createCheckoutUrlAction(params.id, baseUrl, baseUrl)
if (checkoutUrl) {
window.location.href = checkoutUrl
}
} catch (error) {
console.error("Failed to get checkout URL:", error)
}
}
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={handleBuyCredits}>
{createCheckoutUrlSubmission.pending ? "Loading..." : "Buy Credits"}
</button>
</div>
</section>
)
}
function UsageSection() {
const params = useParams()
const dummyUsage = [
{
id: "usage_1",
model: "claude-3-sonnet-20240229",
inputTokens: 1250,
outputTokens: 890,
cost: 125000000, // $1.25 in cents
timeCreated: "2024-02-10T15:30:00Z",
},
{
id: "usage_2",
model: "gpt-4-turbo-preview",
inputTokens: 2100,
outputTokens: 1456,
cost: 340000000, // $3.40 in cents
timeCreated: "2024-02-09T09:45:00Z",
},
{
id: "usage_3",
model: "claude-3-haiku-20240307",
inputTokens: 850,
outputTokens: 620,
cost: 45000000, // $0.45 in cents
timeCreated: "2024-02-08T13:22:00Z",
},
{
id: "usage_4",
model: "gpt-3.5-turbo",
inputTokens: 1800,
outputTokens: 1200,
cost: 85000000, // $0.85 in cents
timeCreated: "2024-02-07T11:15:00Z",
},
]
const usage = createAsync(() => getUsageInfo(params.id))
// const usage = () => dummyUsage
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 PaymentsSection() {
const params = useParams()
const dummyPayments = [
{
id: "pi_1234567890",
amount: 5000000000, // $50.00 in cents
timeCreated: "2024-02-01T10:00:00Z",
},
{
id: "pi_0987654321",
amount: 2500000000, // $25.00 in cents
timeCreated: "2024-01-15T14:30:00Z",
},
]
const payments = createAsync(() => getPaymentsInfo(params.id))
// const payments = () => dummyPayments
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 keys = createAsync(() => listKeys(params.id))
const [copiedKey, setCopiedKey] = createSignal(false)
async function copyKeyToClipboard(text: string) {
try {
await navigator.clipboard.writeText(text)
setCopiedKey(true)
setTimeout(() => setCopiedKey(false), 2000)
} catch (error) {
console.error("Failed to copy to clipboard:", error)
}
}
return (
<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">
<div data-slot="section-title">
<h2>Your API Key</h2>
</div>
<Show when={keys()?.length}>
<div data-slot="key-display">
<div data-slot="key-container">
<code data-slot="key-value">{keys()![0].key}</code>
<button
data-color="primary"
disabled={copiedKey()}
onClick={() => copyKeyToClipboard(keys()![0].key)}
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">
<div data-slot="section-title">
<h2>Next Steps</h2>
</div>
<ol>
<li>Copy your API key above</li>
<li>
Run <code>opencode auth login</code> and select opencode
</li>
<li>Paste your API key when prompted</li>
<li>
Run <code>/models</code> to see available models
</li>
</ol>
</div>
</div>
)
}
export default function () {
const params = useParams()
const keys = createAsync(() => listKeys(params.id))
const usage = createAsync(() => getUsageInfo(params.id))
const isNewUser = createMemo(() => {
const keysList = keys()
const usageList = usage()
return keysList?.length === 1 && (!usageList || usageList.length === 0)
})
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>
<Show when={!isNewUser()} fallback={<NewUserSection />}>
<div data-slot="sections">
<KeysSection />
<BalanceSection />
<UsageSection />
<PaymentsSection />
</div>
</Show>
</div>
)
}

View File

@@ -1,526 +0,0 @@
import type { APIEvent } from "@solidjs/start/server"
import path from "node:path"
import { Database, eq, 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,
cacheWrite5m: 0,
cacheWrite1h: 0,
},
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,
cacheRead: 0,
cacheWrite5m: 0,
cacheWrite1h: 0,
},
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,
cacheRead: 0,
cacheWrite5m: 0,
cacheWrite1h: 0,
},
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,
cacheWrite5m: 0,
cacheWrite1h: 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,
cacheRead: 0,
cacheWrite5m: 0,
cacheWrite1h: 0,
},
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(eq(KeyTable.key, apiKey))
.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 = reasoningTokens ? modelCost.output * reasoningTokens * 100 : undefined
const cacheReadCost = modelCost.cacheRead * cacheReadTokens * 100
const cacheWrite5mCost = cacheWrite5mTokens ? modelCost.cacheWrite5m * cacheWrite5mTokens * 100 : undefined
const cacheWrite1hCost = cacheWrite1hTokens ? modelCost.cacheWrite1h * cacheWrite1hTokens * 100 : undefined
const totalCostInCent =
inputCost +
outputCost +
(reasoningCost ?? 0) +
cacheReadCost +
(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": Math.round(cacheReadCost),
"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,
inputTokens,
outputTokens,
reasoningTokens,
cacheReadTokens,
cacheWriteTokens: (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0),
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 },
)
}
}

View File

@@ -1,20 +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
}
]
}

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
},
)
}

View File

@@ -1,19 +0,0 @@
{
"name": "@opencode/cloud-scripts",
"version": "0.7.2",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"scripts": {
"start": "tsx",
"shell": "sst shell"
},
"dependencies": {
"@opencode/cloud-core": "workspace:*",
"tsx": "4.20.5"
},
"devDependencies": {
"@types/node": "catalog:",
"typescript": "catalog:"
}
}

View File

@@ -1 +0,0 @@
// placeholder

View File

@@ -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],
})
@@ -75,6 +75,7 @@ export const stripeWebhook = new WebhookEndpoint("StripeWebhookEndpoint", {
"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!) },
@@ -120,25 +114,15 @@ 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",
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,
],
path: "packages/console/app",
link: [database, AUTH_API_URL, STRIPE_WEBHOOK_SECRET, STRIPE_SECRET_KEY, ZEN_MODELS],
environment: {
//VITE_DOCS_URL: web.url.apply((url) => url!),
//VITE_API_URL: gateway.url.apply((url) => url!),

10
infra/desktop.ts Normal file
View File

@@ -0,0 +1,10 @@
import { domain } from "./stage"
new sst.cloudflare.StaticSite("Desktop", {
domain: "desktop." + domain,
path: "packages/app",
build: {
command: "bun turbo build",
output: "./dist",
},
})

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}"

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"
}

View File

@@ -6,14 +6,13 @@
"packageManager": "bun@1.2.21",
"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"
"typecheck": "bun turbo typecheck",
"prepare": "husky"
},
"workspaces": {
"packages": [
"cloud/*",
"packages/*",
"packages/console/*",
"packages/sdk/js"
],
"catalog": {
@@ -23,18 +22,19 @@
"@tsconfig/node22": "22.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",
"zod": "4.1.8",
"remeda": "2.26.0",
"solid-js": "1.9.9"
}
},
"dependencies": {
"pulumi-stripe": "0.0.24"
},
"devDependencies": {
"prettier": "3.5.3",
"sst": "3.17.12"
"husky": "9.1.7",
"prettier": "3.6.2",
"sst": "3.17.13",
"turbo": "2.5.6"
},
"repository": {
"type": "git",
@@ -53,9 +53,6 @@
"tree-sitter-bash",
"web-tree-sitter"
],
"overrides": {
"zod": "3.25.76"
},
"patchedDependencies": {
"@solidjs/start@1.1.7": "patches/@solidjs%2Fstart@1.1.7.patch"
}

1
packages/app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
src/assets/theme.css

28
packages/app/AGENTS.md Normal file
View File

@@ -0,0 +1,28 @@
# Agent Guidelines for @opencode/app
## Build/Test Commands
- **Development**: `bun run dev` (starts Vite dev server on port 3000)
- **Build**: `bun run build` (production build)
- **Preview**: `bun run serve` (preview production build)
- **Validation**: Use `bun run typecheck` only - do not build or run project for validation
- **Testing**: Do not create or run automated tests
## Code Style
- **Framework**: SolidJS with TypeScript
- **Imports**: Use `@/` alias for src/ directory (e.g., `import Button from "@/ui/button"`)
- **Formatting**: Prettier configured with semicolons disabled, 120 character line width
- **Components**: Use function declarations, splitProps for component props
- **Types**: Define interfaces for component props, avoid `any` type
- **CSS**: TailwindCSS with custom CSS variables theme system
- **Naming**: PascalCase for components, camelCase for variables/functions, snake_case for file names
- **File Structure**: UI primitives in `/ui/`, higher-level components in `/components/`, pages in `/pages/`, providers in `/providers/`
## Key Dependencies
- SolidJS, @solidjs/router, @kobalte/core (UI primitives)
- TailwindCSS 4.x with @tailwindcss/vite
- Custom theme system with CSS variables
No special rules files found.

34
packages/app/README.md Normal file
View File

@@ -0,0 +1,34 @@
## Usage
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
```bash
$ npm install # or pnpm install or yarn install
```
### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
## Available Scripts
In the project directory, you can run:
### `npm run dev` or `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
### `npm run build`
Builds the app for production to the `dist` folder.<br>
It correctly bundles Solid in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
## Deployment
You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)

24
packages/app/index.html Normal file
View File

@@ -0,0 +1,24 @@
<!doctype html>
<html lang="en" class="h-full bg-background">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.svg" />
<link rel="stylesheet" href="/src/assets/theme.css" />
<title>opencode</title>
</head>
<body class="h-full overscroll-none select-none">
<script>
;(function () {
const savedTheme = localStorage.getItem("theme") || "opencode"
const savedDarkMode = localStorage.getItem("darkMode") !== "false"
document.documentElement.setAttribute("data-theme", savedTheme)
document.documentElement.setAttribute("data-dark", savedDarkMode.toString())
})()
</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.tsx" type="module"></script>
</body>
</html>

48
packages/app/package.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "@opencode/app",
"version": "0.11.7",
"description": "",
"type": "module",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"typecheck": "tsc --noEmit"
},
"license": "MIT",
"devDependencies": {
"@tailwindcss/vite": "4.1.11",
"@types/luxon": "3.7.1",
"@types/node": "catalog:",
"typescript": "catalog:",
"vite": "^6.0.0",
"vite-plugin-icons-spritesheet": "3.0.1",
"vite-plugin-solid": "^2.11.6"
},
"dependencies": {
"@kobalte/core": "0.13.11",
"@opencode-ai/sdk": "workspace:*",
"@shikijs/transformers": "3.9.2",
"@solid-primitives/event-bus": "1.1.2",
"@solid-primitives/resize-observer": "2.1.3",
"@solid-primitives/scroll": "2.1.3",
"@solidjs/router": "0.15.3",
"@thisbeyond/solid-dnd": "0.7.5",
"diff": "8.0.2",
"fuzzysort": "catalog:",
"luxon": "catalog:",
"marked": "16.2.0",
"marked-shiki": "1.2.1",
"remeda": "catalog:",
"shiki": "3.9.2",
"solid-js": "catalog:",
"solid-list": "0.3.0",
"tailwindcss": "4.1.11",
"virtua": "0.42.3"
},
"prettier": {
"semi": false,
"printWidth": 120
}
}

View File

@@ -0,0 +1,163 @@
import type { Plugin } from "vite"
import { readdir, readFile, writeFile } from "fs/promises"
import { join, resolve } from "path"
interface ThemeDefinition {
$schema?: string
defs?: Record<string, string>
theme: Record<string, any>
}
interface ResolvedThemeColor {
dark: string
light: string
}
class ColorResolver {
private colors: Map<string, any> = new Map()
private visited: Set<string> = new Set()
constructor(defs: Record<string, string> = {}, theme: Record<string, any> = {}) {
Object.entries(defs).forEach(([key, value]) => {
this.colors.set(key, value)
})
Object.entries(theme).forEach(([key, value]) => {
this.colors.set(key, value)
})
}
resolveColor(key: string, value: any): ResolvedThemeColor {
if (this.visited.has(key)) {
throw new Error(`Circular reference detected for color ${key}`)
}
this.visited.add(key)
try {
if (typeof value === "string") {
if (value === "none") return { dark: value, light: value }
if (value.startsWith("#")) {
return { dark: value.toLowerCase(), light: value.toLowerCase() }
}
const resolved = this.resolveReference(value)
return { dark: resolved, light: resolved }
}
if (typeof value === "object" && value !== null) {
const dark = this.resolveColorValue(value.dark || value.light || "#000000")
const light = this.resolveColorValue(value.light || value.dark || "#FFFFFF")
return { dark, light }
}
return { dark: "#000000", light: "#FFFFFF" }
} finally {
this.visited.delete(key)
}
}
private resolveColorValue(value: any): string {
if (typeof value === "string") {
if (value === "none") return value
if (value.startsWith("#")) {
return value.toLowerCase()
}
return this.resolveReference(value)
}
return value
}
private resolveReference(ref: string): string {
const colorValue = this.colors.get(ref)
if (colorValue === undefined) {
throw new Error(`Color reference '${ref}' not found`)
}
if (typeof colorValue === "string") {
if (colorValue === "none") return colorValue
if (colorValue.startsWith("#")) {
return colorValue.toLowerCase()
}
return this.resolveReference(colorValue)
}
return colorValue
}
}
function kebabCase(str: string): string {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase()
}
function parseTheme(themeData: ThemeDefinition): Record<string, ResolvedThemeColor> {
const resolver = new ColorResolver(themeData.defs, themeData.theme)
const colors: Record<string, ResolvedThemeColor> = {}
Object.entries(themeData.theme).forEach(([key, value]) => {
colors[key] = resolver.resolveColor(key, value)
})
return colors
}
async function loadThemes(): Promise<Record<string, Record<string, ResolvedThemeColor>>> {
const themesDir = resolve(__dirname, "../../tui/internal/theme/themes")
const files = await readdir(themesDir)
const themes: Record<string, Record<string, ResolvedThemeColor>> = {}
for (const file of files) {
if (!file.endsWith(".json")) continue
const themeName = file.replace(".json", "")
const themeData: ThemeDefinition = JSON.parse(await readFile(join(themesDir, file), "utf-8"))
themes[themeName] = parseTheme(themeData)
}
return themes
}
function generateCSS(themes: Record<string, Record<string, ResolvedThemeColor>>): string {
let css = `/* Auto-generated theme CSS - Do not edit manually */\n:root {\n`
const defaultTheme = themes["opencode"] || Object.values(themes)[0]
if (defaultTheme) {
Object.entries(defaultTheme).forEach(([key, color]) => {
const cssVar = `--theme-${kebabCase(key)}`
css += ` ${cssVar}: ${color.light};\n`
})
}
css += `}\n\n`
Object.entries(themes).forEach(([themeName, colors]) => {
css += `[data-theme="${themeName}"][data-dark="false"] {\n`
Object.entries(colors).forEach(([key, color]) => {
const cssVar = `--theme-${kebabCase(key)}`
css += ` ${cssVar}: ${color.light};\n`
})
css += `}\n\n`
css += `[data-theme="${themeName}"][data-dark="true"] {\n`
Object.entries(colors).forEach(([key, color]) => {
const cssVar = `--theme-${kebabCase(key)}`
css += ` ${cssVar}: ${color.dark};\n`
})
css += `}\n\n`
})
return css
}
export function generateThemeCSS(): Plugin {
return {
name: "generate-theme-css",
async buildStart() {
try {
console.log("Generating theme CSS...")
const themes = await loadThemes()
const css = generateCSS(themes)
const outputPath = resolve(__dirname, "../src/assets/theme.css")
await writeFile(outputPath, css)
console.log(`✅ Generated theme CSS with ${Object.keys(themes).length} themes`)
console.log(` Output: ${outputPath}`)
} catch (error) {
throw new Error(`Theme CSS generation failed: ${error}`)
}
},
}
}

View File

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 377 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#29b6f6" d="M21 16.5c0 .38-.21.71-.53.88l-7.9 4.44c-.16.12-.36.18-.57.18s-.41-.06-.57-.18l-7.9-4.44A.99.99 0 0 1 3 16.5v-9c0-.38.21-.71.53-.88l7.9-4.44c.16-.12.36-.18.57-.18s.41.06.57.18l7.9 4.44c.32.17.53.5.53.88zM12 4.15 6.04 7.5 12 10.85l5.96-3.35zM5 15.91l6 3.38v-6.71L5 9.21zm14 0v-6.7l-6 3.37v6.71z"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#0288d1" d="M2 10v12h14l14-12"/></svg>

After

Width:  |  Height:  |  Size: 110 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ff5722" d="M13.295 11.033V7.65l2.126-2.136c.774-.763.919-1.981.377-2.929a2.38 2.38 0 0 0-2.068-1.217c-.203 0-.435.029-.619.087-1.044.28-1.749 1.246-1.749 2.33v3.13L8.327 9.98a5.75 5.75 0 0 0-1.208 6.214 5.62 5.62 0 0 0 4.243 3.432v.59a.5.5 0 0 1-.483.482h-1.45v1.934h1.45a2.43 2.43 0 0 0 2.416-2.417v-.483c1.962 0 4.02-1.856 4.02-4.591 0-2.223-1.855-4.108-4.02-4.108m0-7.249c0-.222.106-.396.31-.454a.47.47 0 0 1 .54.222.48.48 0 0 1-.077.59l-.773.83V3.785m-1.933 7.732c-.938.619-1.643 1.682-1.894 2.668l1.894.503v2.948a3.73 3.73 0 0 1-2.484-2.185 3.8 3.8 0 0 1 .802-4.098l1.682-1.769zm1.933 6.283v-4.89c1.13 0 2.107 1.062 2.107 2.232 0 1.691-1.227 2.658-2.107 2.658"/></svg>

After

Width:  |  Height:  |  Size: 746 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="#f44336" d="M560-160v-80h120q17 0 28.5-11.5T720-280v-80q0-38 22-69t58-44v-14q-36-13-58-44t-22-69v-80q0-17-11.5-28.5T680-720H560v-80h120q50 0 85 35t35 85v80q0 17 11.5 28.5T840-560h40v160h-40q-17 0-28.5 11.5T800-360v80q0 50-35 85t-85 35zm-280 0q-50 0-85-35t-35-85v-80q0-17-11.5-28.5T120-400H80v-160h40q17 0 28.5-11.5T160-600v-80q0-50 35-85t85-35h120v80H280q-17 0-28.5 11.5T240-680v80q0 38-22 69t-58 44v14q36 13 58 44t22 69v80q0 17 11.5 28.5T280-240h120v80z"/><path fill="#f44336" d="M360-600h80v40h-80zm80 240h40v-200h-40v80h-80v-80h-40v200h40v-80h80zm200-200v-40H530a10 10 0 0 0-10 10v100a10 10 0 0 0 10 10h70v80h-80v40h110a10 10 0 0 0 10-10v-140a10 10 0 0 0-10-10h-70v-40z"/></svg>

After

Width:  |  Height:  |  Size: 758 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#0277bd" d="m2 12 2.9-1.07c.25-1.1.87-1.73.87-1.73a3.996 3.996 0 0 1 5.65 0l1.41 1.41 6.31-6.7c.95 3.81 0 7.62-2.33 10.69L22 19.62s-8.47 1.9-13.4-1.95c-2.63-2.06-3.22-3.26-3.59-4.52zm5.04.21c.37.37.98.37 1.35 0s.37-.97 0-1.34a.96.96 0 0 0-1.35 0c-.37.37-.37.97 0 1.34"/></svg>

After

Width:  |  Height:  |  Size: 348 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="28" height="28" x="2" y="2" fill="#5d4037" rx="4"/><path fill="#ffb74d" d="M20.988 9.999a.96.96 0 0 1-.687-.269 1 1 0 0 1-.263-.704.9.9 0 0 1 .278-.681 1 1 0 0 1 .687-.268.93.93 0 0 1 .703.268 1.046 1.046 0 0 1-.015 1.385.9.9 0 0 1-.703.268M20 12h2v10h-2zm-5.63-1.98-.01-.02h-2.08a.12.12 0 0 0-.1.13 4.5 4.5 0 0 1-.06.74c-.05.13-.08.26-.12.37l-.27.78L8 22h2.14l.75-2h5.24l.79 2h2.16zM11.64 18l1.8-4.84.01.04.02.04L14.95 17l.39 1z"/></svg>

After

Width:  |  Height:  |  Size: 511 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="28" height="28" x="2" y="2" fill="#795548" rx="4"/><path fill="#ffb74d" d="M20.988 9.999a.96.96 0 0 1-.687-.269 1 1 0 0 1-.263-.704.9.9 0 0 1 .278-.681 1 1 0 0 1 .687-.268.93.93 0 0 1 .703.268 1.046 1.046 0 0 1-.015 1.385.9.9 0 0 1-.703.268M20 12h2v10h-2zm-5.63-1.98-.01-.02h-2.08a.12.12 0 0 0-.1.13 4.5 4.5 0 0 1-.06.74c-.05.13-.08.26-.12.37l-.27.78L8 22h2.14l.75-2h5.24l.79 2h2.16zM11.64 18l1.8-4.84.01.04.02.04L14.95 17l.39 1z"/></svg>

After

Width:  |  Height:  |  Size: 511 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="28" height="28" x="2" y="2" fill="#37474f" rx="4"/><path fill="#64b5f6" d="M23.744 14.716a3.7 3.7 0 0 0-1.066-.408 5.4 5.4 0 0 0-1.245-.157 2.1 2.1 0 0 0-.666.085.57.57 0 0 0-.345.24.7.7 0 0 0-.089.324.56.56 0 0 0 .111.313 1.3 1.3 0 0 0 .378.324q.386.217.79.397a7.8 7.8 0 0 1 1.71.877 2.7 2.7 0 0 1 .878.998 2.8 2.8 0 0 1 .256 1.238 2.96 2.96 0 0 1-.434 1.599 2.83 2.83 0 0 1-1.244 1.07 4.75 4.75 0 0 1-2.011.384 7 7 0 0 1-1.511-.156 4.2 4.2 0 0 1-1.134-.385.24.24 0 0 1-.122-.228v-2.092a.14.14 0 0 1 .044-.108c.034-.024.067-.012.1.012a4.6 4.6 0 0 0 1.378.59 4.8 4.8 0 0 0 1.311.18 2 2 0 0 0 .923-.169.56.56 0 0 0 .3-.505.65.65 0 0 0-.267-.48 4.6 4.6 0 0 0-1.089-.565 6.6 6.6 0 0 1-1.578-.866 3 3 0 0 1-.844-1.021 2.76 2.76 0 0 1-.256-1.226 3 3 0 0 1 .378-1.455 2.8 2.8 0 0 1 1.167-1.105A4 4 0 0 1 21.533 12a9 9 0 0 1 1.378.108 3.7 3.7 0 0 1 .956.277.2.2 0 0 1 .11.108.7.7 0 0 1 .023.144v1.96a.15.15 0 0 1-.056.12.28.28 0 0 1-.2 0M12.38 10H9.99v-.03h-2v12h2V18h2.39A3.62 3.62 0 0 0 16 14.38v-.76A3.62 3.62 0 0 0 12.38 10M14 14.38A1.626 1.626 0 0 1 12.38 16H9.99v-4h2.39A1.626 1.626 0 0 1 14 13.62Z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="28" height="28" x="2" y="2" fill="#455a64" rx="4"/><path fill="#64b5f6" d="M23.744 14.716a3.7 3.7 0 0 0-1.066-.408 5.4 5.4 0 0 0-1.245-.157 2.1 2.1 0 0 0-.666.085.57.57 0 0 0-.345.24.7.7 0 0 0-.089.324.56.56 0 0 0 .111.313 1.3 1.3 0 0 0 .378.324q.386.217.79.397a7.8 7.8 0 0 1 1.71.877 2.7 2.7 0 0 1 .878.998 2.8 2.8 0 0 1 .256 1.238 2.96 2.96 0 0 1-.434 1.599 2.83 2.83 0 0 1-1.244 1.07 4.75 4.75 0 0 1-2.011.384 7 7 0 0 1-1.511-.156 4.2 4.2 0 0 1-1.134-.385.24.24 0 0 1-.122-.228v-2.092a.14.14 0 0 1 .044-.108c.034-.024.067-.012.1.012a4.6 4.6 0 0 0 1.378.59 4.8 4.8 0 0 0 1.311.18 2 2 0 0 0 .923-.169.56.56 0 0 0 .3-.505.65.65 0 0 0-.267-.48 4.6 4.6 0 0 0-1.089-.565 6.6 6.6 0 0 1-1.578-.866 3 3 0 0 1-.844-1.021 2.76 2.76 0 0 1-.256-1.226 3 3 0 0 1 .378-1.455 2.8 2.8 0 0 1 1.167-1.105A4 4 0 0 1 21.533 12a9 9 0 0 1 1.378.108 3.7 3.7 0 0 1 .956.277.2.2 0 0 1 .11.108.7.7 0 0 1 .023.144v1.96a.15.15 0 0 1-.056.12.28.28 0 0 1-.2 0M12.38 10H9.99v-.03h-2v12h2V18h2.39A3.62 3.62 0 0 0 16 14.38v-.76A3.62 3.62 0 0 0 12.38 10M14 14.38A1.626 1.626 0 0 1 12.38 16H9.99v-4h2.39A1.626 1.626 0 0 1 14 13.62Z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#e53935" d="M4 5v22a1 1 0 0 0 1 1h22a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1m20 7c-2.926 0-4.21.722-5.012 2H22v4h-4.582C16.34 20.857 14.393 24 8 24v-4c4.559 0 5.14-1.744 6.103-4.632C15.139 12.258 16.559 8 24 8Z"/></svg>

After

Width:  |  Height:  |  Size: 297 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180"><path fill="#7c4dff" d="m79.579 25.741-66.481 115.15h63.305l11.218-19.433H47.613L79.804 65.7l20.005 34.649 11.423-19.783zm42.118 50.221-45.203 78.297h90.408z" paint-order="fill markers stroke"/></svg>

After

Width:  |  Height:  |  Size: 262 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#7986cb" fill-rule="evenodd" d="M6.752 1.158C2.234 1.96-.271 6.943 1.758 11.09c2.537 5.185 10.047 5.142 12.511-.07C16.69 5.9 12.321.17 6.752 1.159m.587 2.335c2.576.517 5.233 1.323 5.326 1.615.26.808.256 4.849-.004 5.34-.066.125-1.209-.012-2.08-.247l-.351-.094-.001-.437c-.005-1.308-.138-2.547-.29-2.7-.176-.176-1.312-.545-3.052-.99L5.78 5.697l-.014-.267c-.033-.6.117-1.95.232-2.093.063-.079.315-.05 1.34.157M4.029 5.39c.5.066 1.083.178 1.492.289l.178.048.03.984c.058 1.844.117 2.13.475 2.29.448.2 2.083.679 3.62 1.061l.34.084-.01.653c-.012.735-.083 1.393-.175 1.617l-.062.15-.261-.03c-.976-.113-4.175-.896-5.567-1.362-.611-.205-.759-.284-.811-.435-.23-.66-.23-4.905 0-5.337.054-.1.08-.1.75-.012"/></svg>

After

Width:  |  Height:  |  Size: 775 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#ff9800" d="M14 10 5 28h12l-2-4h-4l3-6 5 10h4zm1-2 2-4 12 24h-4l-8-16z"/></svg>

After

Width:  |  Height:  |  Size: 151 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="4" height="10" x="2" y="12" fill="#8bc34a" rx="2"/><rect width="4" height="10" x="26" y="12" fill="#8bc34a" rx="2"/><path fill="#8bc34a" d="M8 12h16v12H8zm2 12h4v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2zm8 0h4v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2zm3.545-19.759 2.12-2.12A1 1 0 0 0 22.251.707l-2.326 2.326a7.97 7.97 0 0 0-7.85 0L9.75.707a1 1 0 1 0-1.414 1.414l2.12 2.12A7.97 7.97 0 0 0 8 10h16a7.97 7.97 0 0 0-2.455-5.759M14 8h-2V6h2Zm6 0h-2V6h2Z"/></svg>

After

Width:  |  Height:  |  Size: 509 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24"><path fill="#e53935" d="M9.87 2.5 3.022 5.666l.645 10.178zm4.26 0 6.202 13.344.645-10.178zM12 7.563l-2.451 5.964h4.906zm-3.73 8.959-.954 2.308L12 21.5l4.683-2.67-.953-2.308z"/></svg>

After

Width:  |  Height:  |  Size: 263 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24"><path fill="#f44336" d="M10.355 1.614a10.469 10.483 0 0 1 11.813 7.792 10.327 10.34 0 0 1-1.565 8.673 10.583 10.597 0 0 1-14.819 2.428 10.416 10.43 0 0 1-4.222-7.14 10.641 10.656 0 0 1 .999-5.994 10.498 10.512 0 0 1 7.795-5.76m.27 3.825c-.949 2.08-1.9 4.16-2.83 6.25-.479 1.345-1.127 2.615-1.716 3.915-.174.408-.468.853-.287 1.312a1.088 1.09 0 0 0 1.575.556c.458-.261.566-.828.778-1.272.952-2.405 2.13-4.708 3.11-7.104a7.356 7.366 0 0 1 .776-1.6c.568 1.406 1.186 2.791 1.773 4.19a14.819 14.839 0 0 1 .969 2.197c-1.51-.015-3.02-.004-4.531-.01 2.073 1.233 4.202 2.379 6.305 3.562a1.094 1.094 0 0 0 1.698-1.036c-.425-1.15-1.014-2.237-1.5-3.364-.917-2.393-2.076-4.685-3.097-7.036a2.685 2.689 0 0 0-.738-1.163 1.564 1.566 0 0 0-2.285.602z"/></svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="12" height="12" x="10" y="2" fill="#42a5f5" rx="6"/><rect width="12" height="12" x="18" y="18" fill="#42a5f5" rx="6"/><rect width="12" height="12" x="2" y="18" fill="#42a5f5" rx="6"/><path fill="none" stroke="#42a5f5" stroke-miterlimit="10" stroke-width="3" d="m16 8 8 16M16 8 8 24"/></svg>

After

Width:  |  Height:  |  Size: 363 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#7e57c2" d="M31.93 14.457a.51.51 0 0 0-.506-.457h-2.01a.497.497 0 0 0-.491.559l.014.134c.616 6.284-4.097 12.817-10.29 14.044A13.009 13.009 0 1 1 24.3 6h4.19a16.013 16.013 0 1 0 3.44 8.457"/><circle cx="24.533" cy="4.267" r="4.267" fill="#7e57c2"/><path fill="#7e57c2" d="M17 8h-3L8 24h3z"/><path fill="#7e57c2" d="M15 8h3l6 16h-3zm2.88 13H12v-3h4.75z"/></svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#78909c" d="M25.425 26.498c-1.162 1.736-2.394 3.43-4.27 3.458-1.875.042-2.477-1.106-4.605-1.106-2.142 0-2.8 1.078-4.578 1.148-1.834.07-3.22-1.848-4.396-3.542C5.183 23 3.35 16.63 5.813 12.346a6.84 6.84 0 0 1 5.767-3.514c1.792-.028 3.5 1.217 4.606 1.217 1.092 0 3.164-1.497 5.334-1.273a6.5 6.5 0 0 1 5.095 2.771 6.38 6.38 0 0 0-3.01 5.334 6.18 6.18 0 0 0 3.752 5.656 15.5 15.5 0 0 1-1.932 3.961M17.432 4.1A6.36 6.36 0 0 1 21.548 2a6.13 6.13 0 0 1-1.456 4.466 5.11 5.11 0 0 1-4.13 1.988 5.98 5.98 0 0 1 1.47-4.354"/></svg>

After

Width:  |  Height:  |  Size: 591 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#f44336" d="M6.053 20.055H21.21a3.01 3.01 0 0 1 3.049 2.966 3.01 3.01 0 0 1-3.049 2.966H6.053a3.01 3.01 0 0 1-3.049-2.966 3.01 3.01 0 0 1 3.049-2.966"/><path fill="#ffc107" d="M19.44 25.433 7.179 16.765a2.914 2.914 0 0 1-.674-4.143 3.104 3.104 0 0 1 4.258-.656l12.263 8.668a2.914 2.914 0 0 1 .674 4.143 3.104 3.104 0 0 1-4.258.656Z"/><path fill="#43a047" d="m19.489 8.05 4.683 14.026a2.95 2.95 0 0 1-1.957 3.737 3.067 3.067 0 0 1-3.841-1.904L13.69 9.884a2.95 2.95 0 0 1 1.957-3.738 3.067 3.067 0 0 1 3.842 1.905Z"/><path fill="#448aff" d="M18.363 22.076 23.047 8.05a3.067 3.067 0 0 1 3.841-1.904 2.95 2.95 0 0 1 1.958 3.737L24.162 23.91a3.067 3.067 0 0 1-3.842 1.904 2.95 2.95 0 0 1-1.957-3.737Z"/></svg>

After

Width:  |  Height:  |  Size: 776 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" viewBox="0 0 256 256"><path fill="#00b8d4" fill-rule="evenodd" d="M127.646 17.356c61.588 0 110.999 49.414 110.999 110.29a110.64 110.64 0 0 1-110.999 110.999c-60.873 0-110.29-49.414-110.29-110.999 0-60.873 49.414-110.29 110.29-110.29m27.213 131.77c-12.174 15.756-34.375 18.62-49.414 6.446-15.039-11.459-17.187-33.66-5.013-49.414 12.891-15.039 35.091-17.904 50.131-6.445 15.039 12.174 17.187 34.375 4.297 49.414zm-58.723 72.331 42.252-40.82c-15.756 3.58-32.227.716-45.117-10.026-15.039-11.459-21.484-30.795-19.336-48.699L35.98 163.45s-5.013-9.31-6.446-26.498l66.602-52.278c20.052-14.323 47.266-15.04 66.602 0 21.484 17.187 25.781 48.698 10.027 72.33l-48.699 69.466c-7.161 0-21.484-2.149-27.93-5.013"/></svg>

After

Width:  |  Height:  |  Size: 776 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#66bb6a" d="M6.278 22 6 19.556l3.167-8.723a4.37 4.37 0 0 0 1.944 1.056l-3.055 8.389zm11.666 0-1.777-1.722-3.056-8.39q.556-.138 1.042-.402a4.4 4.4 0 0 0 .903-.653l3.166 8.723zm-5.833-11.111q-1.389 0-2.361-.972-.972-.973-.972-2.361 0-1.084.624-1.932.626-.846 1.598-1.18V2h2.222v2.444a3.27 3.27 0 0 1 1.598 1.18q.624.849.624 1.932 0 1.389-.972 2.36-.972.973-2.36.973Zm0-2.222q.473 0 .792-.32t.32-.791q0-.473-.32-.793a1.08 1.08 0 0 0-.792-.319q-.472 0-.791.32t-.32.792.32.79q.319.32.791.32Z"/></svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#0097a7" d="M2 14h10v2H2zm22-4h2v10h-2z"/><path fill="#0097a7" d="M20 14h10v2H20z"/><path fill="none" stroke="#0097a7" stroke-width="2" d="M2 5h4a10 10 0 0 1 10 10 10 10 0 0 0 10 10h4"/><path fill="#0097a7" d="M11.644 22A8.95 8.95 0 0 1 6 24H2v2h4a10.98 10.98 0 0 0 8.479-4ZM26 4a10.98 10.98 0 0 0-8.479 4h2.835A8.95 8.95 0 0 1 26 6h4V4Z"/></svg>

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#0097a7" d="M4 18V8l5.39 10Zm0 4v3.67A2.33 2.33 0 0 0 6.33 28h8.9l-3.496-6Zm12.444 0 3.177 5.444A11.88 11.88 0 0 0 26.448 22Zm11.419-4A15 15 0 0 0 28 16 12 12 0 0 0 16 4L6 3.995q-.08 0-.158.005L14 18Z"/></svg>

After

Width:  |  Height:  |  Size: 281 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#ff6e40" d="M8 6V2H4a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h4v-4H4V6Zm16-4v4h4v20h-4v4h4a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2Zm-4 4h-2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2m-2 6V8h2v4Zm-4 6h-2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2m-2 6v-4h2v4Zm0-18c0 2 0 2-2 2v2h2v4h2V6Zm8 12c0 2 0 2-2 2v2h2v4h2v-8Z"/></svg>

After

Width:  |  Height:  |  Size: 415 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#757575" d="M15 2H6a2.006 2.006 0 0 0-2 2v22a2.006 2.006 0 0 0 2 2h6v-4H6v-2h6v-2H6v-2h6v-2H6v-2h6v-2h2V4l8 8h2v-1Z"/><path fill="#7c4dff" d="M12 12v18h18V12Zm10 16c-.9 0-2.025-1.267-2.025-3.005-.914 0-.975.464-.975 1.005-.881-.213-1-1.15-1-2h6c0 1.919-2 1.787-2 4m2.542-6a2.5 2.5 0 0 1-2.308-1.641l-.946-2.42a.305.305 0 0 0-.576 0l-.946 2.42A2.5 2.5 0 0 1 17.458 22H16l2.965-7.59a.63.63 0 0 1 .577-.41h2.916a.63.63 0 0 1 .577.41L26 22Z"/></svg>

After

Width:  |  Height:  |  Size: 517 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#7c4dff" d="M12.106 25.849c-1.262-1.156-1.63-3.586-1.105-5.346a5.18 5.18 0 0 0 3.484 1.66 9.68 9.68 0 0 0 5.882-.734c.215-.106.413-.247.648-.39a3.5 3.5 0 0 1 .16 1.555 4.26 4.26 0 0 1-1.798 3.021c-.404.3-.832.569-1.25.852a2.613 2.613 0 0 0-1.15 3.372l.048.161a3.4 3.4 0 0 1-1.5-1.285 3.6 3.6 0 0 1-.578-1.962 9 9 0 0 0-.05-1.037c-.114-.831-.504-1.204-1.238-1.225a1.45 1.45 0 0 0-1.507 1.18c-.012.056-.028.112-.046.178M4.901 20a17.75 17.75 0 0 1 7.4-2l2.913-8.38a.765.765 0 0 1 1.527 0L19.7 18a14.24 14.24 0 0 1 7.399 2S20.704 2.877 20.692 2.842C20.51 2.33 20.202 2 19.787 2h-7.619c-.415 0-.71.33-.904.842z"/></svg>

After

Width:  |  Height:  |  Size: 686 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ef5350" d="M8.203 5.447 5.83 6.777l1.329-2.374-1.33-2.374 2.374 1.33 2.374-1.33-1.33 2.374 1.33 2.374zm11.394 9.305 2.374-1.329-1.33 2.374 1.33 2.373-2.374-1.329-2.374 1.33 1.33-2.374-1.33-2.374zm2.374-12.724-1.33 2.374 1.33 2.374-2.374-1.33-2.374 1.33 1.33-2.374-1.33-2.374 2.374 1.33zm-8.223 10.236 2.317-2.316-2.013-2.013-2.317 2.317zm.978-5.212 2.222 2.222c.37.35.37.968 0 1.338L5.867 21.694c-.37.37-.987.37-1.339 0l-2.222-2.221c-.37-.352-.37-.969 0-1.34l11.081-11.08c.37-.37.988-.37 1.34 0z"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#ef5350" d="M16 2a14 14 0 1 0 14 14A14 14 0 0 0 16 2m6 10h-4v8a4 4 0 1 1-4-4 3.96 3.96 0 0 1 2 .555V8h6Z"/></svg>

After

Width:  |  Height:  |  Size: 185 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><defs><linearGradient xlink:href="#a" id="i" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse"/><linearGradient id="a" x1="-3.881" x2="2.377" y1="-1.442" y2="4.304"><stop offset="0" stop-color="#ba68c8"/><stop offset="1" stop-color="#7e57c2"/></linearGradient><linearGradient xlink:href="#b" id="j" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse"/><linearGradient id="b" x1=".729" x2="-.971" y1=".844" y2="-1.477"><stop offset="0" stop-color="#5e35b1"/><stop offset=".14" stop-color="#8e24aa"/><stop offset=".29" stop-color="#ad1457"/><stop offset=".84" stop-color="#c2185b"/><stop offset="1" stop-color="#ec407a"/></linearGradient><linearGradient xlink:href="#c" id="k" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse"/><linearGradient id="c" x1="-2.839" x2="2.875" y1="-6.936" y2="1.017"><stop offset="0" stop-color="#ba68c8"/><stop offset="1" stop-color="#7e57c2"/></linearGradient><linearGradient xlink:href="#d" id="l" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse"/><linearGradient id="d" x1="-8.212" x2="1.02" y1="-4.691" y2="2.882"><stop offset="0" stop-color="#ba68c8"/><stop offset="1" stop-color="#7e57c2"/></linearGradient><linearGradient xlink:href="#e" id="m" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse"/><linearGradient id="e" x1="-1.404" x2="4.19" y1="-2.309" y2="2.62"><stop offset="0" stop-color="#ba68c8"/><stop offset="1" stop-color="#7e57c2"/></linearGradient><linearGradient xlink:href="#f" id="n" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse"/><linearGradient id="f" x1="1.911" x2=".204" y1="2.539" y2=".204"><stop offset="0" stop-color="#7e57c2"/><stop offset=".14" stop-color="#7b1fa2"/><stop offset=".29" stop-color="#ad1457"/><stop offset=".84" stop-color="#c2185b"/><stop offset="1" stop-color="#ec407a"/></linearGradient><linearGradient xlink:href="#g" id="o" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse"/><linearGradient id="g" x1="-3.881" x2="2.377" y1="-1.738" y2="5.19"><stop offset="0" stop-color="#ba68c8"/><stop offset="1" stop-color="#7e57c2"/></linearGradient><linearGradient xlink:href="#h" id="p" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse"/><linearGradient id="h" x1=".112" x2=".901" y1=".897" y2=".116"><stop offset="0" stop-color="#7e57c2"/><stop offset=".14" stop-color="#8e24aa"/><stop offset=".53" stop-color="#c2185b"/><stop offset=".79" stop-color="#c2185b"/><stop offset="1" stop-color="#ec407a"/></linearGradient></defs><g stroke-linejoin="round" stroke-miterlimit="1.414" clip-rule="evenodd"><path fill="url(#i)" d="M8.002 6.127 4.117 8.719.116 2.723 4 .13z" transform="translate(11.282 3.07)scale(.47102)"/><path fill="url(#j)" d="m9.179 1.887 6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="translate(12.215 13.552)scale(.47102)"/><path fill="url(#k)" d="m7.3 1.88 1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="translate(8.41 16.686)scale(.47102)"/><path fill="url(#l)" d="M2.328 1.146 4.016.02l2.619 3.925L2.75 6.537l-1.46-2.19 2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="translate(16.99 11.686)scale(.47102)"/><path fill="url(#m)" d="m5.346 9.155-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="translate(2.738 8.18)scale(.47102)"/><path fill="url(#n)" d="m14.533 9.934 1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="translate(4.753 2.36)scale(.47102)"/><path fill="url(#o)" d="M6.235 7.177 4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="translate(11.32 3.106)scale(.47102)"/><path fill="#673ab7" d="m9.632 19.05-.545-.818 2.215-1.478.546.817zm7.965-5.315-.545-.817 1.035-.691.545.817z"/><path fill="#7e57c2" d="m5.256 12.492-.564-.845 2.216-1.478.563.845zm7.965-5.315-.564-.845 1.035-.69.564.844z"/><path fill="#880e4f" d="m16.538 14.441-3.724 2.485-.545-.817 3.724-2.485z"/><path fill="#ad1457" d="m11.598 7.039.564.844-3.724 2.485-.564-.844z"/><path fill="#ab47bc" d="m4.2 6.363.703 1.054-1.053.702-.703-1.053z"/><path fill="#7e57c2" d="m7.996 18.99.703 1.054-1.054.703-.702-1.054z"/><path fill="url(#p)" d="M8.372 38.294.017 29.876 29.749.08l8.636 8.201z" transform="rotate(11.282 -5.61 25.53)scale(.47102)"/></g></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#f44336" d="M15.787 13.71c-.275 0-.587 0-.918.047 1.098.796 1.865 1.847 1.865 3.267v2.367h5.68v-2.367c0-2.206-4.42-3.314-6.627-3.314m-7.575 0c-2.206 0-6.628 1.108-6.628 3.314v2.367H14.84v-2.367c0-2.206-4.421-3.314-6.628-3.314m0-1.894a2.84 2.84 0 0 0 2.841-2.84 2.84 2.84 0 0 0-2.84-2.84 2.84 2.84 0 0 0-2.841 2.84 2.84 2.84 0 0 0 2.84 2.84m7.575 0a2.84 2.84 0 0 0 2.84-2.84 2.84 2.84 0 0 0-2.84-2.84 2.84 2.84 0 0 0-2.84 2.84 2.84 2.84 0 0 0 2.84 2.84"/></svg>

After

Width:  |  Height:  |  Size: 532 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ffc400" d="M8.48 4.17c.334.574 1.047.798 1.696.636A7.5 7.5 0 0 1 12 4.583c.62 0 1.223.075 1.799.217.647.159 1.357-.065 1.691-.64.39-.668.116-1.532-.63-1.751A10.1 10.1 0 0 0 12 2c-1.006 0-1.977.146-2.894.419-.743.22-1.015 1.083-.627 1.75Z"/><path fill="#ad1457" d="M5.039 4.772c.564-.535 1.458-.34 1.848.331.333.572.176 1.292-.284 1.769a7.4 7.4 0 0 0-1.456 2.17c-.242.552-.762.958-1.367.958-.854 0-1.496-.781-1.191-1.572a10 10 0 0 1 2.45-3.656"/><path fill="#cfd8dc" d="M3.197 12c.718 0 1.32.583 1.444 1.286.613 3.483 3.675 6.13 7.359 6.13s6.746-2.647 7.359-6.13c.124-.703.726-1.286 1.444-1.286.719 0 1.279.581 1.187 1.289C21.353 18.203 17.123 22 12 22s-9.353-3.797-9.99-8.711C1.918 12.58 2.478 12 3.197 12"/><path fill="#ff5252" d="M20.203 9.958c.857 0 1.5-.786 1.19-1.578a10 10 0 0 0-2.458-3.632c-.564-.533-1.455-.336-1.845.333-.333.573-.174 1.295.289 1.772a7.4 7.4 0 0 1 1.459 2.155c.243.548.762.95 1.365.95"/><path fill="#cfd8dc" d="M7.133 9.32c-.442-.488.053-1.262.657-1.027l4.912 1.91c1.114.434 1.538 1.84.862 2.855a1.785 1.785 0 0 1-2.83.222l-3.6-3.96Z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#ffc400"
d="M8.48 4.17c.334.574 1.047.798 1.696.636A7.5 7.5 0 0 1 12 4.583c.62 0 1.223.075 1.799.217.647.159 1.357-.065 1.691-.64.39-.668.116-1.532-.63-1.751A10.1 10.1 0 0 0 12 2c-1.006 0-1.977.146-2.894.419-.743.22-1.015 1.083-.627 1.75Z" />
<path fill="#ad1457"
d="M5.039 4.772c.564-.535 1.458-.34 1.848.331.333.572.176 1.292-.284 1.769a7.4 7.4 0 0 0-1.456 2.17c-.242.552-.762.958-1.367.958-.854 0-1.496-.781-1.191-1.572a10 10 0 0 1 2.45-3.656" />
<path fill="currentColor"
d="M3.197 12c.718 0 1.32.583 1.444 1.286.613 3.483 3.675 6.13 7.359 6.13s6.746-2.647 7.359-6.13c.124-.703.726-1.286 1.444-1.286.719 0 1.279.581 1.187 1.289C21.353 18.203 17.123 22 12 22s-9.353-3.797-9.99-8.711C1.918 12.58 2.478 12 3.197 12" />
<path fill="#ff5252"
d="M20.203 9.958c.857 0 1.5-.786 1.19-1.578a10 10 0 0 0-2.458-3.632c-.564-.533-1.455-.336-1.845.333-.333.573-.174 1.295.289 1.772a7.4 7.4 0 0 1 1.459 2.155c.243.548.762.95 1.365.95" />
<path fill="currentColor"
d="M7.133 9.32c-.442-.488.053-1.262.657-1.027l4.912 1.91c1.114.434 1.538 1.84.862 2.855a1.785 1.785 0 0 1-2.83.222l-3.6-3.96Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#4caf50" d="M25.333 4H6.667A2.657 2.657 0 0 0 4 6.667v18.666A2.667 2.667 0 0 0 6.667 28h18.666A2.667 2.667 0 0 0 28 25.333V6.667A2.667 2.667 0 0 0 25.333 4m-2.495 6.22a4 4 0 0 0-.163 1.01q0 .266-.058.83a9 9 0 0 0-.04.719c0 .584-.031 1.443-.092 2.55q-.074 1.253-.088 2.502c0 .412.032 1.057.097 1.91.067.865.1 1.534.1 1.988a1.62 1.62 0 0 1-.505 1.197 1.65 1.65 0 0 1-1.225.475 1.92 1.92 0 0 1-1.233-.466 1.51 1.51 0 0 1-.554-1.19q0-.644-.06-1.934-.047-.99-.056-1.979 0-.198.003-.376c-.805.065-1.766.198-2.867.398q-1.522.277-3.045.562-.032.61-.11 1.65a30 30 0 0 0-.087 2.017 1.62 1.62 0 0 1-.506 1.192 1.73 1.73 0 0 1-1.224.474l-.048.001a1.7 1.7 0 0 1-1.157-.479 1.62 1.62 0 0 1-.502-1.2c0-.615.05-1.513.155-2.738.104-1.182.157-2.077.157-2.661q0-1.15.057-3.46.054-2.302.053-3.442a1.62 1.62 0 0 1 .508-1.196 1.68 1.68 0 0 1 1.222-.478 1.7 1.7 0 0 1 1.206.484 1.63 1.63 0 0 1 .5 1.19q0 .687-.055 2.07-.036 1.01-.044 2.023.001.23-.065.905a7 7 0 0 0-.022.251l2.825-.532a28 28 0 0 1 3.086-.395q.037-.83.095-2.76a4.8 4.8 0 0 1 .466-1.778c.421-.926.957-1.395 1.591-1.395a1.75 1.75 0 0 1 1.166.434l.003.002a1.58 1.58 0 0 1 .566 1.228 1.5 1.5 0 0 1-.05.397"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#1976d2" d="M12.002 2a10 10 0 0 0-10 10 10 10 0 0 0 10 10 10 10 0 0 0 10-10 10 10 0 0 0-10-10m.139 4.419q.642 0 1.07.294.431.294.731.731l5.71 8.262H9.026l1.707-2.35h3.15q.443 0 .77.028a11 11 0 0 1-.443-.62q-.253-.376-.485-.704l-1.64-2.417-4.29 6.063H4.45l5.86-8.262q.285-.396.723-.71.437-.315 1.108-.315"/></svg>

After

Width:  |  Height:  |  Size: 384 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#64b5f6" d="M3.98 22.01h1.803v4.208H9.99v1.803H3.98Z"/><path fill="#1565c0" d="M3.98 10.991v5.51l3.505 3.61 1.503-1.606 4.508 4.508-1.502 1.502 3.506 3.506h5.51a1 1 0 0 0 1.001-1.002v-8.014L12.995 9.99H4.982a1 1 0 0 0-1.003 1.001Z"/><path fill="#1e88e5" d="M8.317 18.44a1 1 0 0 1-.125-1.265L16.407 4.87a2 2 0 0 1 1.666-.891h8.946A1 1 0 0 1 28.02 4.98v8.946a2 2 0 0 1-.891 1.667l-12.305 8.215a1 1 0 0 1-1.265-.126Z"/><path fill="#64b5f6" d="m8.976 21.542 7.648-7.648 1.48 1.481-7.647 7.648Z"/><path fill="#42a5f5" d="m11.68 21.801-1.481-1.48 6.426-6.427 1.48 1.481Z"/><path fill="#90caf9" d="M22.011 12.995a3.006 3.006 0 0 0 .096-6.011h-.096a3.006 3.006 0 0 0 0 6.01Z"/></svg>

After

Width:  |  Height:  |  Size: 747 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#01579b" d="M12.001 4h7.102l-7.372 23.181a1.14 1.14 0 0 1-1.073.819H5.13A1.166 1.166 0 0 1 4 26.801a1.3 1.3 0 0 1 .06-.385l6.87-21.599A1.14 1.14 0 0 1 12.001 4"/><path fill="#1976d2" d="M22.32 20H11.06a.537.537 0 0 0-.522.55.57.57 0 0 0 .166.408l7.236 6.716a1.1 1.1 0 0 0 .775.325h6.376Z"/><path fill="#29b6f6" d="M21.071 4.816A1.14 1.14 0 0 0 20.001 4h-7.915a1.14 1.14 0 0 1 1.072.815l6.868 21.599a1.22 1.22 0 0 1-.71 1.52 1.1 1.1 0 0 1-.362.064h7.915A1.166 1.166 0 0 0 28 26.8a1.3 1.3 0 0 0-.06-.385L21.072 4.817Z"/></svg>

After

Width:  |  Height:  |  Size: 596 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#fdd835" d="M18.23 11.21q-.045-.24-1.32-1.65c-.02-.19.29-.45.9-.8l1.74-1.55c.39-.5.62-1.28.69-2.38l-.02-.26c-.07-.78-.63-1.4-1.69-1.89-.63-.42-1.76-.65-3.38-.68-1.35.11-3.11.59-5.28 1.43-.6.43-1.28.86-2.04 1.28l.01.14.21-.08c.08-.01.13.03.14.11l.13-.07.07-.01.01.06c0 .07-.47.44-1.76 1.35l-.06.12c-.31.02-.61.25-.91.67l.08.12.25-.09.18.24c.32-.33.66-.62 1.03-.87.19.05.29.11.44.16 1.02-.75 2.03-1.3 3.04-1.64l.01.14c-.2.27-.32.42-.38.42l.1.23c.01.19-2.55 7-6.66 14.44l.08.19c.35-.08.58-.17.75-.26l.01.13.4-.03-.67 1.76.14.06c.57-.64 1-1.29 1.3-1.88 1.67-.49 2.94-.97 3.82-1.44.88-.08 1.56-.31 2.02-.7l.92-.47c1.27-.98 2.22-1.67 2.87-2.08 1.33-.98 2.2-1.93 2.6-2.85zm-3.46 2.31L13 14.91c-1.29.85-2 1.3-2.09 1.3-2.07 1.13-3.36 1.72-3.86 1.76l-.05.01c.04-.23.96-2.12 2.75-5.67.78-.06 2.02-.43 3.71-1.1l.41-.03c.85-.08 1.49.09 1.91.49l.03.26c-.31.9-.67 1.44-1.04 1.59m1.09-5.78q-.27.33-1.5 1.11c-.27.03-1.27.42-3.01 1.18l-.28-.05-.01-.12c-.02-.25.09-.57.34-.95.13-.7.28-1.12.44-1.2l1.45-3.28c-.02-.22.29-.35.93-.46l.21-.02.01.18 1.16-.16c1.15-.1 1.75.14 1.8.7l.13-.02-.03-.32.15-.02c.35.19.52.4.54.68.02.18-.08.41-.29.68-.09.01-.14-.06-.15-.18l-.14.01-.03.4c-.58.87-1.01 1.31-1.27 1.34z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#00bfa5" d="m14 12-6-2V2h6Zm-6 0 4 2.058L8 16Zm0 18V18l6-2v4l-2 10Zm10-18 6-2V2h-6Zm6 0-4 2.058L24 16Zm0 18V18l-6-2v4l2 10Z"/></svg>

After

Width:  |  Height:  |  Size: 204 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#81c784" d="m153.491 50.983 102.508 102.508-102.508 102.508L50.983 153.491z"/><path fill="#43a047" d="M50.983 153.491v102.508l102.508 102.508V255.999z"/><path fill="#81c784" d="m358.507 50.983 102.508 102.508-102.508 102.508-102.508-102.508z"/><path fill="#43a047" d="M461.015 153.491v102.508L358.507 358.507V255.999zm-205.016 0 102.508 102.508-102.508 102.508-102.508-102.508z"/><path fill="#2e7d32" d="M255.999 358.507v102.508L153.491 358.507V255.999z"/><path fill="#1b5e20" d="m255.999 358.507 102.508-102.508v102.508L255.999 461.015z"/></svg>

After

Width:  |  Height:  |  Size: 620 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="#c62828" d="M128 704v128c0 70.692 57.308 128 128 128h608c17.728 0 32-14.272 32-32V704z"/><path fill="#ffe082" d="M704 704v192h128V704z"/><path fill="#fff8e1" d="M192 704v96c0 53.184 42.816 96 96 96h544a96 96 0 0 1-96-96 96 96 0 0 1 96-96z"/><path fill="#ff1744" d="M320 832h192v192l-96-96-96 96z"/><path fill="#f44336" d="M256 64c-70.692 0-128 57.308-128 128v640c0 11.088 1.557 21.787 4.207 32.047C146.767 807.565 197.672 768.07 256 768h608c17.728 0 32-14.272 32-32V96c0-17.728-14.272-32-32-32z"/><path fill="#ffeb3b" d="M256 192c-70.912 0-128 57.088-128 128v64c0-70.912 57.088-128 128-128h448v320H256c-70.912 0-128 57.088-128 128v64c0-70.912 57.088-128 128-128h512V192z"/></svg>

After

Width:  |  Height:  |  Size: 755 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#e64a19" d="M26.471 5.736c7.383 3.577 2.04 13.636-5.547 17.984-5.998 3.44-18.128 5.76-18.877-2.22-.738-7.863 7.61-6.698 11.575-8.67 4.032-2.003 6.854-9.998 12.85-7.093zm-11.684 8.89c-1.167.438-3.695.194-3.479 2.094.215 1.932 3.483.908 5.243.097 1.788-.82 3.415-2.475 2.27-3.496-1.424-1.268-2.421.698-4.034 1.305"/></svg>

After

Width:  |  Height:  |  Size: 392 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#ffca28" d="M6.915 9.906q.42.413 1.084.404t.98-.472l3.92-5.775-5.88 3.85q-.472.309-.498.945t.394 1.048M7.999 2q1.033 0 1.987.284.953.283 1.793.85l-1.33.825q-.577-.292-1.198-.438-.622-.146-1.252-.146-2.327 0-3.963 1.607T2.4 8.875q0 .722.201 1.427.201.704.569 1.323h9.659q.402-.653.586-1.358t.184-1.46q0-.62-.149-1.204t-.446-1.134l.84-1.307q.525.808.831 1.72.306.91.324 1.89.017.98-.228 1.873-.245.894-.717 1.702-.193.31-.525.481-.333.172-.7.172h-9.66q-.367 0-.7-.172t-.524-.481q-.455-.774-.7-1.642T1 8.875q0-1.427.551-2.673T3.056 4.02q.954-.937 2.231-1.479Q6.565 2 8 2zm.123 5.38"/></svg>

After

Width:  |  Height:  |  Size: 659 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#00bcd4" d="M6.915 9.906q.42.413 1.084.404t.98-.472l3.92-5.775-5.88 3.85q-.472.309-.498.945t.394 1.048M7.999 2q1.033 0 1.987.284.953.283 1.793.85l-1.33.825q-.577-.292-1.198-.438-.622-.146-1.252-.146-2.327 0-3.963 1.607T2.4 8.875q0 .722.201 1.427.201.704.569 1.323h9.659q.402-.653.586-1.358t.184-1.46q0-.62-.149-1.204t-.446-1.134l.84-1.307q.525.808.831 1.72.306.91.324 1.89.017.98-.228 1.873-.245.894-.717 1.702-.193.31-.525.481-.333.172-.7.172h-9.66q-.367 0-.7-.172t-.524-.481q-.455-.774-.7-1.642T1 8.875q0-1.427.551-2.673T3.056 4.02q.954-.937 2.231-1.479Q6.565 2 8 2zm.123 5.38"/></svg>

After

Width:  |  Height:  |  Size: 659 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#0288d1" d="M6.915 9.906q.42.413 1.084.404t.98-.472l3.92-5.775-5.88 3.85q-.472.309-.498.945t.394 1.048M7.999 2q1.033 0 1.987.284.953.283 1.793.85l-1.33.825q-.577-.292-1.198-.438-.622-.146-1.252-.146-2.327 0-3.963 1.607T2.4 8.875q0 .722.201 1.427.201.704.569 1.323h9.659q.402-.653.586-1.358t.184-1.46q0-.62-.149-1.204t-.446-1.134l.84-1.307q.525.808.831 1.72.306.91.324 1.89.017.98-.228 1.873-.245.894-.717 1.702-.193.31-.525.481-.333.172-.7.172h-9.66q-.367 0-.7-.172t-.524-.481q-.455-.774-.7-1.642T1 8.875q0-1.427.551-2.673T3.056 4.02q.954-.937 2.231-1.479Q6.565 2 8 2zm.123 5.38"/></svg>

After

Width:  |  Height:  |  Size: 659 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="#795548" d="M96 832h832c17.728 0 32 14.272 32 32v64c0 17.728-14.272 32-32 32H96c-17.728 0-32-14.272-32-32v-64c0-17.728 14.272-32 32-32"/><path fill="#4caf50" d="M160 192h64c17.728 0 32 14.272 32 32v512c0 17.728-14.272 32-32 32h-64c-17.728 0-32-14.272-32-32V224c0-17.728 14.272-32 32-32"/><path fill="#f44336" d="M512 96c0-17.728-14.272-32-32-32H352c-17.728 0-32 14.272-32 32v640c0 17.728 14.272 32 32 32h128c17.728 0 32-14.272 32-32z"/><path fill="#2196f3" d="m530.161 158.902 57.333-27.693a31.804 31.804 0 0 1 42.634 14.936l262.693 548.17c7.66 15.984.977 35.057-14.982 42.766l-57.333 27.693a31.804 31.804 0 0 1-42.634-14.936L515.18 201.668c-7.66-15.983-.977-35.057 14.982-42.766z"/><path fill="#ffeb3b" d="M320 192v64h192v-64zm0 384v64h192v-64z"/></svg>

After

Width:  |  Height:  |  Size: 830 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="#795548" d="M96 832h832c17.728 0 32 14.272 32 32v64c0 17.728-14.272 32-32 32H96c-17.728 0-32-14.272-32-32v-64c0-17.728 14.272-32 32-32"/><path fill="#4caf50" d="M160 192h64c17.728 0 32 14.272 32 32v512c0 17.728-14.272 32-32 32h-64c-17.728 0-32-14.272-32-32V224c0-17.728 14.272-32 32-32"/><path fill="#f44336" d="M512 96c0-17.728-14.272-32-32-32H352c-17.728 0-32 14.272-32 32v640c0 17.728 14.272 32 32 32h128c17.728 0 32-14.272 32-32z"/><path fill="#ffeb3b" d="M320 192v64h192v-64zm0 384v64h192v-64z"/><path fill="#bbdefb" d="M608 320h256c17.728 0 32 14.272 32 32v384c0 17.728-14.272 32-32 32H608c-17.728 0-32-14.272-32-32V352c0-17.728 14.272-32 32-32"/><path fill="#2196f3" d="M608 320c-17.673 0-32 14.327-32 32v352c35.346 0 64-28.654 64-64v-32a32 32 0 0 1 32-32c17.673 0 32-14.327 32-32v-64a32 32 0 0 1 32-32c17.673 0 32-14.327 32-32v-96z"/><path d="M745.606 339.205 924.74 473.693a15.965 15.965 0 0 1 3.19 22.401 15.965 15.965 0 0 1-22.403 3.19l-179.133-134.49a15.965 15.965 0 0 1-3.19-22.401 15.965 15.965 0 0 1 22.402-3.19z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#fbc02d" d="M3 18S4.15 6.885 7 3l5 1-1 3H9v7h1c1.9-2.915 5.783-3.98 8.157-2.915 4.475 1.915 2.998 5.967.148 7.905C16.025 20.548 10.113 23.05 3 18"/></svg>

After

Width:  |  Height:  |  Size: 226 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 74 74"><path fill="#42a5f5" d="M37 9 22.745 33.69a32.2 32.2 0 0 1 16.869-.584l4.818 1.137-4.533 19.22-4.825-1.137c-5.93-1.399-11.628 1.716-14.036 6.685l-4.46-2.158c3.404-7.029 11.425-11.285 19.637-9.347l2.259-9.58A27.23 27.23 0 0 0 5 64.424l64 .001z"/></svg>

After

Width:  |  Height:  |  Size: 311 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><defs><linearGradient id="a" x1="64.01" x2="32.99" y1="65.26" y2="89.48" gradientUnits="userSpaceOnUse"><stop offset=".18" stop-color="#1565c0"/><stop offset="1" stop-color="#1e88e5"/></linearGradient></defs><path fill="#1e88e5" d="M2.985 3.333a.618.618 0 0 0-.617.716l2.621 15.914a.84.84 0 0 0 .822.701h12.576a.62.62 0 0 0 .618-.519l2.627-16.09a.618.618 0 0 0-.617-.716zm11.039 11.501H10.01L8.923 9.16h6.074z"/><path fill="url(#a)" d="M59.67 60.12H40.9L37.75 78.5h-13L9.4 96.73a2.7 2.7 0 0 0 1.75.66h40.74a2 2 0 0 0 2-1.68z" transform="translate(2.368 -9.404)scale(.30877)"/></svg>

After

Width:  |  Height:  |  Size: 685 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill-opacity=".05" viewBox="0 0 400 400"><g fill="#e53935" fill-opacity="1"><path d="M350.738 186.163c-1.32-13.024-4.224-26.312-8.36-38.72-11.88-35.464-33.968-71.808-61.864-96.888-1.232-1.056-5.896-3.872-7.656-2.904-4.576 2.552 4.048 20.064 5.104 23.232 6.512 19.36 10.648 39.864 5.984 60.104-6.248 26.752-26.752 45.496-54.12 47.784-15.048 1.232-30.184-.44-45.232 1.32-22.528 2.64-45.496 10.384-59.84 28.864-1.672 2.112-3.168 4.488-4.576 6.952h-.352c-5.544.616-11.088-1.76-13.816-3.256-.704-.44-1.408-.792-1.936-1.056-16.72-9.24-29.04-29.92-36.608-46.992-3.432-7.92-6.336-16.192-8.184-24.552-.88-3.784-.968-7.744-1.144-11.616-.088-2.376.264-5.72-1.056-7.832-2.904-4.576-6.6-.176-7.216 3.52-.968 6.072-1.848 12.056-1.584 18.216.44 10.384 3.344 20.68 7.04 30.36 5.456 14.256 13.112 27.368 23.056 39.072 4.136 4.84 8.536 9.328 13.288 13.464 4.224 3.784 9.592 6.776 12.76 11.616 3.696 5.544 4.312 12.408 3.96 18.832-.88 16.984-1.408 32.912 3.432 49.456 4.224 14.696 9.504 29.744 18.304 42.328 4.4 6.248 9.856 12.848 15.84 17.512 4.048 3.168 11.704 3.52 7.304-8.096-9.768-25.784-10.648-52.536 4.576-76.648 12.76-20.064 35.288-37.928 60.72-34.76 37.4 4.664 63.448 38.984 61.6 75.68-.528 10.296-.88 19.096-4.136 28.776-1.32 3.872-2.288 8.8-1.32 12.848 1.584 6.864 9.24 4.312 12.584-.176 9.064-12.32 18.568-24.288 27.104-36.96 27.808-41.536 41.36-89.584 36.344-139.48"/><path d="M141.21 85.051c.616 2.024 1.232 4.224 1.672 6.6.088.968.352 2.024.88 2.992 2.288 5.984 7.832 9.24 13.024 12.32 3.168 1.936 8.888 3.784 12.408 5.192 4.576 1.848 14.432-.528 19.096-.88 10.736-.88 20.68-4.664 30.536 1.056-50.512 59.224-2.816 72.424 34.144 43.912 42.24-32.56 2.464-109.384 2.464-109.384s-.88-5.984-16.896-9.504a52 52 0 0 0-4.488-2.112c-15.84-7.304-30.096 4.664-41.536 14.432-3.344 2.816-6.6 5.632-10.12 8.272-4.752 3.52-9.856 6.424-15.224 8.976-5.632 2.64-12.32 5.632-18.568 5.896-.88 0-2.552.176-4.312.528-2.728.264-4.136.968-4.752 2.2-1.056.88-1.76 2.112-1.584 3.696.176 2.2 1.232 4.048 2.376 5.456.352.088.616.264.88.352"/></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g fill="#ff9800" fill-rule="evenodd"><path d="M14.004 19a5 5 0 0 1 4.993-5.001 5 5 0 0 1 5.008 4.985A5 5 0 0 1 19.028 24a5 5 0 0 1-5.024-4.97z" paint-order="stroke fill markers"/><path d="m23.148 7.152-4.355-4.451s-1.488-1.534-3.022-.046-.046 3.022-.046 3.022l.165.264c.693.69 1.412 1.368 2.105 2.058h-12s-2 0-2 2 2 2 2 2h4l-6 6-1.332 1.41s-1.503 1.503 0 3.007c1.503 1.503 3.006 0 3.006 0l2.327-2.417.063.19q.06.555.173 1.09a11.02 11.02 0 0 0 8.599 8.508 11 11 0 0 0 2.216.213c6.068-.028 10.967-4.965 10.949-11.034 0-5.452-4-8.967-6.848-11.815zm-4.162 4.847a7 7 0 1 1-6.99 7.044V19a7 7 0 0 1 6.99-7"/></g></svg>

After

Width:  |  Height:  |  Size: 672 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path fill="#f9a825" d="M130.974 23.383c57.809 1.624 103.262 49.782 101.638 107.591s-49.782 103.262-107.59 101.639C67.303 230.989 21.85 183.01 23.383 125.293c1.533-57.81 49.602-103.443 107.41-101.91zm-.541 10.823c-51.766-1.353-94.875 39.59-96.137 91.447-1.353 51.766 39.59 94.875 91.357 96.137 51.766 1.353 94.875-39.59 96.137-91.357 1.443-51.856-39.5-94.875-91.357-96.227.09 0 0 0 0 0"/><path fill="#f9a825" d="M137.9 93.403c-4.149 3.968-2.525 12.806 3.878 19.57s15.241 8.838 19.209 4.78 2.706-12.987-3.788-19.751-15.422-8.748-19.57-4.78zm52.217-25.162c8.207 8.568 14.43 18.758 18.398 29.851 0 0 2.706 7.395-5.862 7.395H181.73s-6.674-.54-6.944 5.14c-.451 7.035-.27 12.988-.27 12.988.27 4.058 1.803 8.026 4.328 11.183l21.554 22.727a9.184 9.184 0 0 1 1.082 12.355c-10.912 18.578-28.408 32.286-49.06 38.509-6.314 1.894-6.945-3.247-6.765-6.764 0-2.255 2.616-52.397 2.616-52.397.721-5.411-.992-10.912-4.78-14.881-6.764-7.215-11.003-11.814-11.003-11.814s-4.78-4.78-11.634-11.904c-3.788-3.878-9.018-5.862-14.43-5.501H54.027c-3.427 0-8.658-.812-6.403-7.035 7.305-20.292 21.915-37.066 41.124-46.896 3.878-2.705 9.199-1.984 12.265 1.714l21.554 22.727c3.066 2.705 6.944 4.329 11.003 4.78 0 0 5.862.45 12.987.36 5.591 0 5.501-6.764 5.501-6.764s.902-13.888 1.173-20.923c-.27-2.976 1.894-5.591 4.78-5.862.991-.09 1.893.09 2.795.451 11.003 4.69 21.013 11.634 29.22 20.292z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><circle cx="128" cy="128" r="97.4" fill="#37474f"/><path fill="#f9a825" d="M130.974 23.383c57.809 1.624 103.262 49.782 101.638 107.591s-49.782 103.262-107.59 101.639C67.303 230.989 21.85 183.01 23.383 125.293c1.533-57.81 49.602-103.443 107.41-101.91zm-.541 10.823c-51.766-1.353-94.875 39.59-96.137 91.447-1.353 51.766 39.59 94.875 91.357 96.137 51.766 1.353 94.875-39.59 96.137-91.357 1.443-51.856-39.5-94.875-91.357-96.227.09 0 0 0 0 0"/><path fill="#f9a825" d="M137.9 93.403c-4.149 3.968-2.525 12.806 3.878 19.57s15.241 8.838 19.209 4.78 2.706-12.987-3.788-19.751-15.422-8.748-19.57-4.78zm52.217-25.162c8.207 8.568 14.43 18.758 18.398 29.851 0 0 2.706 7.395-5.862 7.395H181.73s-6.674-.54-6.944 5.14c-.451 7.035-.27 12.988-.27 12.988.27 4.058 1.803 8.026 4.328 11.183l21.554 22.727a9.184 9.184 0 0 1 1.082 12.355c-10.912 18.578-28.408 32.286-49.06 38.509-6.314 1.894-6.945-3.247-6.765-6.764 0-2.255 2.616-52.397 2.616-52.397.721-5.411-.992-10.912-4.78-14.881-6.764-7.215-11.003-11.814-11.003-11.814s-4.78-4.78-11.634-11.904c-3.788-3.878-9.018-5.862-14.43-5.501H54.027c-3.427 0-8.658-.812-6.403-7.035 7.305-20.292 21.915-37.066 41.124-46.896 3.878-2.705 9.199-1.984 12.265 1.714l21.554 22.727c3.066 2.705 6.944 4.329 11.003 4.78 0 0 5.862.45 12.987.36 5.591 0 5.501-6.764 5.501-6.764s.902-13.888 1.173-20.923c-.27-2.976 1.894-5.591 4.78-5.862.991-.09 1.893.09 2.795.451 11.003 4.69 21.013 11.634 29.22 20.292z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#7c4dff" d="M8.613 11.997c1.333 0 2.588.621 3.389 1.677l3.454 4.552a.28.28 0 0 1 .025.297l-1.991 3.825a.284.284 0 0 1-.477.04l-7.901-10.39zm2.375-10.385 7.9 10.39h-3.5a4.25 4.25 0 0 1-3.39-1.676L8.546 5.774a.28.28 0 0 1-.025-.297l1.99-3.825a.284.284 0 0 1 .478-.04z"/></svg>

After

Width:  |  Height:  |  Size: 346 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400"><path fill="#5d4037" d="M376.834 196.261c-18.912-18.172-113.486-29.517-143.327-32.819a88 88 0 0 0 3.692-10.58c4.068-1.78 8.46-3.438 13-4.822.553 1.632 3.159 7.885 4.644 10.853 60.004 1.655 63.085-44.591 65.525-57.26 2.387-12.389 2.265-24.359 22.847-46.241-30.663-8.936-74.759 13.85-89.53 47.762-5.55-2.08-11.114-3.615-16.615-4.565-3.943-15.905-24.474-60.215-78.352-60.215-68.215 0-142.567 56.276-142.567 151.542 0 80.078 54.672 150.258 85.559 150.258 13.49 0 25.094-10.103 27.818-19.158 2.284 6.209 9.292 25.51 11.593 30.424 3.402 7.267 19.134 13.554 26.018 6.014 8.852 4.917 25.095 7.88 33.947-5.235 17.049 3.606 32.12-6.56 32.45-18.691 8.365-.447 12.469-12.193 10.642-21.547-1.346-6.887-15.732-31.599-21.343-40.13 11.108 9.035 39.243 11.593 42.66.006 17.909 14.057 45.817 6.679 48.03-4.753 21.761 5.654 46.72-6.764 42.621-21.803 34.958-2.418 30.483-39.611 20.675-49.037z"/><path fill="#03a9f4" d="M279.494 116.935c7.529-14.938 16.99-31.25 28.94-41.34-13.153 5.3-26.139 21.146-33.817 38.083a118 118 0 0 0-11.893-6.646c10.71-22.862 35.598-41.955 63.025-43.447-18.37 16.662-11.85 51.29-26.954 69.623-4.322-4.342-14.247-12.72-19.301-16.273m-11.876 24.326c.008-.572.222-4.981.624-6.994-1.054-.248-7.601-1.529-11.015-1.449-.249 4.288 1.802 11.581 3.828 15.972 13.956-.292 24.036-4.472 29.969-8.314-5.051-2.354-13.67-4.448-20.224-5.7-.732 1.513-2.531 5.368-3.182 6.485"/><g stroke-width=".973" transform="translate(10.989 32.73)scale(.81733)"><path fill="#4caf50" d="M250.54 277.39c.004.024.015.057.018.082-2.165-4.657-4.463-10.314-7.208-17.708 10.688 15.557 44.184 7.533 42.427-6.407 16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455 28 5.4 54.832 10.783 63.256 12.938-5.595 9.123-18.339 15.566-37.549 11.089 10.38 14.14-9.773 31.105-37.844 21.76 6.18 13.883-18.814 26.38-47.22 11.91.361 13.889-35.24 15.488-49.315.143zm55.543-70.194c32.497 2.495 86.238 7.34 119.51 11.997-2.102-10.828-7.844-13.921-25.905-18.772-19.425 2.072-68.706 6.913-93.604 6.776z"/><path fill="#ffca28" d="M285.78 253.36c16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455-33.103-6.383-67.84-12.788-75.719-13.908 4.78.254 12.702.797 22.59 1.556 24.899.137 74.18-4.704 93.604-6.775-31.452-7.975-95.666-19.613-140.01-22.48-2.055 3.003-5.833 8.097-12.413 13.51-19.403 41.053-54.557 68.34-93.454 68.34-11.335 0-24.018-1.912-38.233-6.456-8.865 9.497-46.661 16.694-77.329 1.641 24.326 56.961 80.74 94.984 143.19 94.984 52.591 0 75.912-53.704 70.808-67.914-1.238-3.45-6.145-14.889-8.891-22.283 10.689 15.556 44.185 7.532 42.429-6.408z"/><path fill="#e0e0e0" d="M253.91 145.27c4.644-2.526 20.69-12.253 35.981-15.908a68 68 0 0 1-.536-5.12c-10.032 2.403-28.945 10.51-39.784-.661 22.866 6.9 34.283-6.149 51.09-6.149 10.014 0 24.305 2.798 35.57 7.22-9.061-8.37-38.772-33.63-75.558-33.717-8.213 9.957-17.09 31.526-6.764 54.334z"/><path fill="#f4511e" d="M115.58 253.33c14.215 4.544 26.898 6.457 38.233 6.457 38.896 0 74.05-27.29 93.454-68.341-14.351 11.978-39.291 22.228-78.241 22.228 34.694-7.866 64.56-25.156 79.753-50.427-10.68-16.998-22.263-54.603 7.07-84.33-4.512-14.497-26.475-52.766-75.095-52.766-84.85 0-155.17 71.001-155.17 166.15 0 22.525 4.547 43.65 12.67 62.664 30.666 15.054 68.462 7.858 77.327-1.64z"/><path fill="#ffca28" d="M141.03 108.45c0 21.644 17.546 39.191 39.19 39.191s39.192-17.548 39.192-39.191-17.548-39.191-39.192-39.191-39.19 17.547-39.19 39.191"/><path fill="#5d4037" d="M156.76 108.45c0 12.958 10.507 23.463 23.463 23.463 12.96 0 23.464-10.506 23.464-23.463 0-12.959-10.504-23.464-23.464-23.464-12.957 0-23.463 10.506-23.463 23.464"/><ellipse cx="180.22" cy="98.044" fill="#fafafa" rx="13.673" ry="8.501"/></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ff4081" d="M21.085 13.343a4.35 4.35 0 0 1-1.812 3.788l.738 1.429c.22.431.25.94.058 1.39a1.68 1.68 0 0 1-1.017.959l-.758.24a1.62 1.62 0 0 1-1.784-.527l-2.032-2.398a5.1 5.1 0 0 1-2.34-1.055 5 5 0 0 1-1.438.22 4.2 4.2 0 0 1-2.398-.757 5 5 0 0 1-1.553.211 5.6 5.6 0 0 1-2.206-.431 3.94 3.94 0 0 1-2.33-3.462c-.077-.69.038-1.39.336-2.024a3.3 3.3 0 0 1-.068-2.234 4.3 4.3 0 0 1 1.86-2.148c.557-1.62 2.12-2.704 3.837-2.589a4.404 4.404 0 0 1 5.59-.355 5 5 0 0 1 1.247-.163A4.16 4.16 0 0 1 18.37 5.01a4.61 4.61 0 0 1 3.433 4.286 5.05 5.05 0 0 1-.825 3.002c.067.345.106.69.106 1.045m-4.795-1.352c.547.067.978.48.978 1.026a.96.96 0 0 1-.959.959h-.604a4.97 4.97 0 0 1-1.553 2.196c.24.086.489.134.738.201 4.92-.067 4.344-3.068 4.344-3.116a2.486 2.486 0 0 0-2.58-2.388.96.96 0 0 1-.958-.959.96.96 0 0 1 .958-.959c1.18.029 2.312.47 3.194 1.247a5 5 0 0 0 .076-.854c-.057-1.189-.594-2.224-2.752-2.426-1.198-2.838-4.22-1.266-4.22-.383-.028.22.202.69.24.719a.96.96 0 0 1 .96.959.96.96 0 0 1-.96.959 2.25 2.25 0 0 1-1.37-.537c-.461.297-.988.48-1.535.537-.547.048-.997-.336-1.026-.863a.93.93 0 0 1 .844-1.055c.153-.02.901-.134.901-.739 0-.632.24-1.237.652-1.716-.882-.24-1.831.077-2.79 1.237-1.765-.278-2.484-.038-3.011 1.832-.911.45-1.39.767-1.602 1.726a5.65 5.65 0 0 1 3.088.24.97.97 0 0 1 .566 1.236.96.96 0 0 1-1.237.566 2.93 2.93 0 0 0-2.206-.057c-.307.259-.307.796-.307 1.218 0 .71.355 1.37.96 1.754a3.5 3.5 0 0 0 1.64.384 6 6 0 0 1-.375-.777.995.995 0 0 1 1.88-.652c.383 1.093 1.361 1.841 2.512 1.966a3.59 3.59 0 0 0 3.06-2.043c.22-1.323 1.284-1.438 2.454-1.438m1.918 7.163-.595-1.246-.68.153.958 1.199zm-4.46-8.256a.96.96 0 0 0-.872-.988 2.56 2.56 0 0 0-1.85.643 2.85 2.85 0 0 0-.806 2.1.96.96 0 0 0 .959.959.95.95 0 0 0 .959-.96c0-.258.067-.517.22-.728a.64.64 0 0 1 .413-.144c.527.029.978-.364.978-.882z"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 140"><path fill="#ffca28" d="M70 10.172A59.83 59.83 0 0 0 10.172 70 59.83 59.83 0 0 0 70 129.828 59.83 59.83 0 0 0 129.828 70 59.83 59.83 0 0 0 70 10.172m-4.836 8.785C65.66 23 66.516 26.28 67.736 29.18c4.779-4.287 10.265-7.546 16.041-9.02-.981 3.938-1.357 7.295-1.261 10.43 6.026-2.314 12.349-3.404 18.3-2.706-3.182 2.413-5.482 4.717-7.128 7.015-2.201 12.074 6.858 20.43 14.779 24.551a5.13 5.13 0 0 1 5.183-3.888 5.128 5.128 0 0 1 3.7 8.435V64c-.487 1.055-2.002 2.343-3.496 3.219-4.076 2.39-11.173 5.736-20.915 7.39.045 1.214.077 2.453.077 3.747 0 4.817-.485 8.291-1.385 10.699-3.3 13.313-12.648 26.76-24.695 31.95.357-4.082.197-7.484-.402-10.591-5.582 3.219-11.646 5.278-17.623 5.52h-.002c1.785-3.662 2.855-6.878 3.412-9.976-6.347.996-12.727.742-18.377-1.17 2.93-2.732 5.054-5.314 6.673-7.96-6.292-1.344-12.169-3.87-16.766-7.686 3.822-1.544 6.795-3.239 9.3-5.197-5.426-3.517-10.034-7.998-12.972-13.23 4.012-.07 7.321-.568 10.3-1.453-3.786-5.215-6.468-11.032-7.333-16.951 3.861 1.405 7.196 2.133 10.36 2.355-1.662-6.22-2.081-12.605-.768-18.436 3.03 2.634 5.824 4.48 8.63 5.815.677-6.406 2.576-12.52 5.893-17.496 1.926 3.622 3.914 6.392 6.111 8.672 2.93-5.754 6.9-10.798 11.791-14.262zM91.63 38.514c-2.395 5.514-1.665 11.297-.555 18.732a2.138 2.138 0 0 0 .28-4.178 3.419 3.419 0 1 1 .092 6.704c.574 3.882 1.157 8.18 1.421 13.125a67 67 0 0 0 3.25-.649c6.616-1.487 12.258-3.801 16.871-6.506.45-.264.884-.563 1.276-.867.366-.557.333-.957.035-1.285-4.831-1.245-10.891-4.53-15.258-8.795-4.764-4.653-7.427-10.164-7.412-16.281"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 140"><g stroke-width=".855" transform="translate(10.508 10.205)"><circle cx="59.492" cy="59.795" r="59.828" fill="#ffca28"/><path fill="#37474f" d="M54.656 8.752c-4.89 3.464-8.862 8.508-11.791 14.262-2.198-2.28-4.185-5.05-6.111-8.672-3.318 4.976-5.216 11.09-5.893 17.496-2.807-1.335-5.6-3.18-8.63-5.814-1.314 5.83-.895 12.216.767 18.436-3.164-.223-6.498-.95-10.36-2.356.865 5.92 3.548 11.737 7.333 16.951-2.978.885-6.287 1.383-10.3 1.453 2.939 5.233 7.547 9.714 12.972 13.23-2.505 1.959-5.478 3.654-9.299 5.198 4.596 3.815 10.474 6.341 16.766 7.685-1.62 2.647-3.743 5.228-6.674 7.96 5.65 1.912 12.03 2.166 18.377 1.17-.556 3.098-1.626 6.314-3.412 9.975h.002c5.977-.24 12.042-2.3 17.623-5.52.6 3.108.76 6.51.402 10.593 12.047-5.19 21.395-18.638 24.695-31.951.9-2.408 1.385-5.881 1.385-10.7 0-1.293-.031-2.531-.076-3.745 9.742-1.655 16.839-5.001 20.914-7.39 1.494-.877 3.01-2.165 3.496-3.22v-.002a5.128 5.128 0 0 0-3.7-8.435 5.13 5.13 0 0 0-5.183 3.889c-7.92-4.122-16.98-12.477-14.779-24.551 1.646-2.299 3.947-4.603 7.13-7.016-5.952-.698-12.276.392-18.302 2.707-.095-3.135.28-6.492 1.262-10.43-5.776 1.473-11.262 4.733-16.041 9.02-1.22-2.902-2.076-6.18-2.572-10.223zm26.465 19.557c-.015 6.117 2.648 11.628 7.412 16.281 4.366 4.265 10.426 7.55 15.258 8.795.298.328.331.728-.035 1.285-.392.304-.825.603-1.276.867-4.612 2.704-10.256 5.019-16.87 6.506q-1.607.361-3.25.649c-.265-4.945-.848-9.243-1.422-13.125a3.419 3.419 0 1 0-.092-6.703 2.138 2.138 0 0 1-.28 4.177c-1.11-7.435-1.84-13.218.555-18.732" data-mit-no-recolor="true"/></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#212121" d="M26 10H6v14h6v2h8v-2h6z"/><path fill="#ffab40" d="M27.897 9.794a6.86 6.86 0 0 0-4.35-3.55A7.97 7.97 0 0 0 18 4h-4a7.97 7.97 0 0 0-5.548 2.244 6.86 6.86 0 0 0-4.35 3.55A19.9 19.9 0 0 0 2 18.702V20a4 4 0 0 0 4 4v-8h2v6a4 4 0 0 0 4 4v-2a2 2 0 0 1-2-2v-2h2v2h2v-2h4v2h2v-2h2v2a2 2 0 0 1-2 2v2a4 4 0 0 0 4-4v-6h2v8a4 4 0 0 0 4-4v-1.298a19.9 19.9 0 0 0-2.103-8.908M10 14v-2h2v2Zm4 4v-2h4v2Zm8-4h-2v-2h2Z"/><path fill="#f44336" d="M16 24a6.8 6.8 0 0 1-2 .996V28a2 2 0 0 0 4 0v-3.004A6.8 6.8 0 0 1 16 24"/></svg>

After

Width:  |  Height:  |  Size: 588 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="#0277bd"><path d="M7.488 2.94h-1.51v4.273L7.82 9.054H5.61L3.197 6.642V2.94H1.595v4.383l3.278 3.278h4.42l1.584 1.584H6.64l3.573 3.683-5.23 5.194h2.062l5.23-5.267-1.989-1.99H20.86v.664l-4.567 2.725-3.831 3.868h2.173l2.615-2.652 5.157-3.094v-3.13h-4.862l-1.658-1.658 1.879-1.879V4.45H16.2v3.5l-1.528 1.51-1.363-1.428V4.45h-1.473v4.273l3.445 3.462h-2.102L7.488 6.55z"/><path d="M15.48 14.763h-2.062l.995 1.068z"/></g></svg>

After

Width:  |  Height:  |  Size: 488 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#26a69a" d="M12 18h4v2h-4z"/><path fill="#26a69a" d="M4 4v24h24V4Zm14 15.5a.5.5 0 0 1-.5.5H16v2h1.5a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5H16v1.5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5V18h1.5a.5.5 0 0 1 .5.5Zm8-2a.5.5 0 0 1-.5.5H22v2h2a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-3.5a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5H24v-2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h3.5a.5.5 0 0 1 .5.5Z"/><path fill="#26a69a" d="M12 22h4v2h-4z"/></svg>

After

Width:  |  Height:  |  Size: 520 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#00e676" d="m12 22-8-4V8l8 4zm8-14v10h4l4-4"/><path fill="#00c853" d="m12 22 8-4V8l-8 4zm8 6 8-4V14l-8 4z"/></svg>

After

Width:  |  Height:  |  Size: 186 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#fff8e1" d="M30 17.045a9.8 9.8 0 0 0-.32-2.306l-.004.034a11.2 11.2 0 0 0-5.762-6.786c-3.495-1.89-5.243-3.326-6.8-3.811h.003c-1.95-.695-3.949.82-5.825 1.927-4.52 2.481-9.573 5.45-9.28 11.417.008-.029.017-.052.026-.08a9.97 9.97 0 0 0 3.934 7.257l-.01-.006C13.747 31.473 30.05 27.292 30 17.045"/><path fill="#37474f" d="M19.855 20.236A.8.8 0 0 0 19.26 20h-6.514a.8.8 0 0 0-.596.236.51.51 0 0 0-.137.463 4.37 4.37 0 0 0 1.641 2.339 4.2 4.2 0 0 0 2.349.926 4.2 4.2 0 0 0 2.343-.926 4.37 4.37 0 0 0 1.642-2.339.5.5 0 0 0-.132-.463Z"/><ellipse cx="22.5" cy="18.5" fill="#f8bbd0" rx="2.5" ry="1.5"/><ellipse cx="9.5" cy="18.5" fill="#f8bbd0" rx="2.5" ry="1.5"/><circle cx="10" cy="16" r="2" fill="#37474f"/><circle cx="22" cy="16" r="2" fill="#37474f"/><path fill="#455a64" d="M9.996 18A2 2 0 1 0 8 15.996V16a2 2 0 0 0 1.996 2"/><circle cx="9" cy="15" r="1" fill="#fafafa"/><circle cx="21" cy="15" r="1" fill="#fafafa"/></svg>

After

Width:  |  Height:  |  Size: 990 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#fff8e1" d="M15.696 27.002a13.73 13.73 0 0 1-9.071-3.062 8.86 8.86 0 0 1-3.6-6.505c-.252-5.091 3.813-7.747 8.748-10.455.28-.165.537-.322.793-.48a7.8 7.8 0 0 1 3.52-1.5 2 2 0 0 1 .695.118 14.8 14.8 0 0 1 2.95 1.576c.972.6 2.182 1.348 3.707 2.173a10.14 10.14 0 0 1 5.274 6.147A8.8 8.8 0 0 1 29 17.035a8.15 8.15 0 0 1-2.525 5.959 15.6 15.6 0 0 1-10.778 4.008Z"/><path fill="#37474f" d="M16.087 6a1 1 0 0 1 .358.06l.038.013.037.012a14.5 14.5 0 0 1 2.684 1.46 72 72 0 0 0 3.767 2.205 9.17 9.17 0 0 1 4.767 5.493A8 8 0 0 1 28 17.055a7.18 7.18 0 0 1-2.234 5.233 14.6 14.6 0 0 1-10.07 3.714 12.74 12.74 0 0 1-8.415-2.816l-.027-.024-.029-.023a7.98 7.98 0 0 1-3.202-5.758c-.223-4.516 3.431-6.89 8.231-9.525l.027-.015.027-.015q.389-.231.783-.474A7.4 7.4 0 0 1 16.087 6m0-2c-1.618 0-3.248 1.19-4.795 2.103-4.52 2.481-9.56 5.41-9.267 11.376a9.9 9.9 0 0 0 3.942 7.215 14.77 14.77 0 0 0 9.73 3.308c7.122 0 14.335-4.134 14.303-10.957a9.6 9.6 0 0 0-.322-2.29 11.16 11.16 0 0 0-5.764-6.768c-3.495-1.89-5.242-3.326-6.798-3.811A3 3 0 0 0 16.086 4Z"/><path fill="#37474f" d="M19.855 20.236A.8.8 0 0 0 19.26 20h-6.514a.8.8 0 0 0-.596.236.51.51 0 0 0-.137.463 4.37 4.37 0 0 0 1.641 2.339 4.2 4.2 0 0 0 2.349.926 4.2 4.2 0 0 0 2.343-.926 4.37 4.37 0 0 0 1.642-2.339.5.5 0 0 0-.132-.463Z"/><ellipse cx="22.5" cy="18.5" fill="#f8bbd0" rx="2.5" ry="1.5"/><ellipse cx="9.5" cy="18.5" fill="#f8bbd0" rx="2.5" ry="1.5"/><circle cx="10" cy="16" r="2" fill="#37474f"/><circle cx="22" cy="16" r="2" fill="#37474f"/><path fill="#455a64" d="M9.996 18A2 2 0 1 0 8 15.996V16a2 2 0 0 0 1.996 2"/><circle cx="9" cy="15" r="1" fill="#fafafa"/><circle cx="21" cy="15" r="1" fill="#fafafa"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#0288d1" d="M19.563 22A5.57 5.57 0 0 1 14 16.437v-2.873A5.57 5.57 0 0 1 19.563 8H24V2h-4.437A11.563 11.563 0 0 0 8 13.563v2.873A11.564 11.564 0 0 0 19.563 28H24v-6Z"/></svg>

After

Width:  |  Height:  |  Size: 245 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#0288d1" d="M11.563 22A5.57 5.57 0 0 1 6 16.437v-2.873A5.57 5.57 0 0 1 11.563 8H14V2h-2.437A11.563 11.563 0 0 0 0 13.563v2.873A11.564 11.564 0 0 0 11.563 28H14v-6Zm20.129-4.131A5.17 5.17 0 0 0 28 14c3.39-.894 4.268-5.241 2.792-8.108-3.305-6.304-14.028-4.545-15.407 2.381l4.89 1.255a3.17 3.17 0 0 1 3.04-2.754 3 3 0 0 1 1.814.702c1.19.911 1.249 3.785-.353 4.232A9 9 0 0 1 22 12h-2v4h2c1.7.107 3.362.577 4.23 2.313a3.4 3.4 0 0 1 .377 1.636 3.25 3.25 0 0 1-.297 1.464c-.919 1.985-3.984 2.166-5.407.749a4.43 4.43 0 0 1-1.285-2.143l-4.89 1.429c2.447 10.449 19.993 7.76 16.964-3.58"/></svg>

After

Width:  |  Height:  |  Size: 656 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><g transform="translate(0 -822.52)"><rect width="107.25" height="156.59" x="405.55" y="967.22" fill="#0097a7" rx="12.306" ry="12.31" transform="matrix(-.98339 .18149 .60192 .79856 0 0)"/><rect width="108.34" height="123.15" x="-1156.5" y="1461.9" fill="#3f51b5" rx="10.69" ry="12.31" transform="matrix(-.98528 .17093 -.59175 .80612 0 0)"/><path fill="#3f51b5" d="M52.112 965.158c-1.343 3.515-26.292 23.248-25.744 27.277.548 4.03 29.812 16.023 32.04 19.027s10.545 41.668 13.603 42.5 18.828-31.274 21.548-32.932 32.808 2.503 34.15-1.01c1.343-3.515-18.174-35.352-18.721-39.381s9.732-40.12 7.502-43.125-30.06 9.427-33.118 8.594-26.793-27.3-29.514-25.643-.405 41.177-1.747 44.693z"/></g></svg>

After

Width:  |  Height:  |  Size: 750 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#4fc3f7" d="M20 22v-3.53q-.008-.155-.011-.31-.003-.436-.041-.87a5.3 5.3 0 0 0-.18-.994 2.9 2.9 0 0 0-1.026-1.563A4.42 4.42 0 0 0 16.017 14a4.5 4.5 0 0 0-2.762.74 2.9 2.9 0 0 0-1.05 1.57 5 5 0 0 0-.186 1.073q-.029.448-.014.897l.004.191v3.53Z"/><path fill="#4fc3f7" d="M29 19c0-7.409-5.268-13-13-13S3 11.591 3 19c-.003 2.317 0 5 1 7.026v-.84c.001-1.673 2.264-3.002 4-3.186v-4.438C8 12.38 10.388 9.931 16 10c5.612-.07 8 2.38 8 7.562V22c1.736.184 3.999 1.513 4 3.187v.839C29 24 29.003 21.317 29 19"/></svg>

After

Width:  |  Height:  |  Size: 574 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#00e676" d="M14 12h6v-1a1 1 0 0 1 1-1h7V4h-6a8 8 0 0 0-8 8m6 0h6v6h-6zm-6 6v2.65A1.35 1.35 0 0 1 12.65 22h-1.3A1.35 1.35 0 0 1 10 20.65v-1.3A1.35 1.35 0 0 1 11.35 18zv-6h-2.65A7.35 7.35 0 0 0 4 19.35v1.3A7.35 7.35 0 0 0 11.35 28h1.3A7.35 7.35 0 0 0 20 20.65V18Z"/></svg>

After

Width:  |  Height:  |  Size: 342 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#f44336" d="M13.15 7.455a1.94 1.94 0 0 1-1.938-1.94c0-1.07.87-1.94 1.939-1.94 1.07 0 1.94.87 1.94 1.94s-.87 1.94-1.94 1.94M12 2C6.477 2 2 6.477 2 12c0 2.348.811 4.506 2.166 6.212 1.092-1.532 2.258-2.977 3.721-4.18.042-.035.143-.11.272-.203a2.92 2.92 0 0 0 1.15-1.876v-.012c.37-2.438 1.371-3.279 4.152-3.279q.37.001.786.02c1.423.067 2.243.473 2.34.685a.57.57 0 0 1 .027.363l-.111-.015c-.878-.109-2.231.16-2.419 1.117-.105.544.02 1.143.072 1.693.054.567.104 1.139.099 1.711-.003.044-.035.266-.005.29-1.514-1.449-5.014.37-6.116 1.17q.17-.058.34-.122c1.05-.357 4.24-1.314 5.47-.256 1.043 1.277.104 3.634-.673 4.802a9.7 9.7 0 0 1-1.64 1.87q.184.009.369.01c5.523 0 10-4.477 10-10S17.523 2 12 2"/></svg>

After

Width:  |  Height:  |  Size: 768 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#ff7043" d="M16 10a2.847 2.847 0 0 0 3-2.663v-.003a2.32 2.32 0 0 0-.435-1.372L16 2l-2.565 3.96A2.33 2.33 0 0 0 13 7.331 2.847 2.847 0 0 0 15.998 10zm6.134 13.376L20.708 22l-1.44 1.375a4.917 4.917 0 0 1-6.52 0L11.334 22l-1.466 1.375A4.79 4.79 0 0 1 4 23.871V29a1 1 0 0 0 1 1h22a1 1 0 0 0 1-1v-5.129a4.79 4.79 0 0 1-5.866-.497M24 14h-6.667v-2h-2.666v2H8a4.145 4.145 0 0 0-4 4.09v1.415A2.56 2.56 0 0 0 6.614 22a2.53 2.53 0 0 0 1.84-.726l2.88-2.71 2.813 2.71a2.764 2.764 0 0 0 3.693 0l2.826-2.71 2.868 2.71A2.649 2.649 0 0 0 28 19.505V18.09A4.145 4.145 0 0 0 24 14"/></svg>

After

Width:  |  Height:  |  Size: 641 B

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