Compare commits
562 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c503b9c70 | ||
|
|
659f23de30 | ||
|
|
2252b5ca1b | ||
|
|
c78dad8db5 | ||
|
|
0569e8652c | ||
|
|
f2d5b32e52 | ||
|
|
b2f5ea7c30 | ||
|
|
8eb8f1a16c | ||
|
|
ad93d50ab7 | ||
|
|
73c5c328a8 | ||
|
|
72a13212e2 | ||
|
|
78bcf35f37 | ||
|
|
3a3ee3ecfd | ||
|
|
34e045c275 | ||
|
|
e187918ce0 | ||
|
|
7ac17c7833 | ||
|
|
b05d5b30fb | ||
|
|
57c08b01b7 | ||
|
|
08efb9cdf6 | ||
|
|
8b51da768c | ||
|
|
862407c674 | ||
|
|
a381aa7e0d | ||
|
|
4dcda3d53d | ||
|
|
479cca29a5 | ||
|
|
e38814c597 | ||
|
|
4d42daa9a3 | ||
|
|
130345bd5d | ||
|
|
0baee00be4 | ||
|
|
e0acd5d361 | ||
|
|
1e7d78a215 | ||
|
|
7a6cb85617 | ||
|
|
20530104ce | ||
|
|
d22754dd68 | ||
|
|
db0e1ebb80 | ||
|
|
e83a47debe | ||
|
|
eed48e76de | ||
|
|
ac70c1e813 | ||
|
|
ac0bed16a2 | ||
|
|
fab8ab2840 | ||
|
|
09ff8eba00 | ||
|
|
9bd2ea5e5f | ||
|
|
aa525482ae | ||
|
|
285605737d | ||
|
|
4201fe6e01 | ||
|
|
203f3312ee | ||
|
|
0c77c46dc7 | ||
|
|
52bb43eebd | ||
|
|
e020f5355e | ||
|
|
9b86d4e595 | ||
|
|
f3d3b41a3f | ||
|
|
a959199f09 | ||
|
|
5e3a59d5a2 | ||
|
|
9f23d85e20 | ||
|
|
54e15b38ea | ||
|
|
d66b903e7f | ||
|
|
4425c66732 | ||
|
|
0dd0250285 | ||
|
|
c347056246 | ||
|
|
2a5255ac8f | ||
|
|
d9175be989 | ||
|
|
cebbfcfbaa | ||
|
|
de415be4f6 | ||
|
|
e8ce113b7f | ||
|
|
8ca02b7664 | ||
|
|
3f5bb21f16 | ||
|
|
fe114c41b5 | ||
|
|
d90fd8a5d7 | ||
|
|
9363c15b4a | ||
|
|
3325823f23 | ||
|
|
4b4d8da1ad | ||
|
|
d531dff8d3 | ||
|
|
923bf36593 | ||
|
|
d6e499dd48 | ||
|
|
aec1497c6e | ||
|
|
f5a77c8cd8 | ||
|
|
bc524eeb44 | ||
|
|
725f658260 | ||
|
|
af1080dd42 | ||
|
|
63e54541fe | ||
|
|
c3f7a88c1c | ||
|
|
586a8b7b31 | ||
|
|
981744f802 | ||
|
|
a3bb4a3c85 | ||
|
|
06ba1f76dc | ||
|
|
076c8b2ca1 | ||
|
|
9a90939ac4 | ||
|
|
123a136093 | ||
|
|
4126fedbd4 | ||
|
|
145d185e6f | ||
|
|
6b32667c7d | ||
|
|
d8401e1937 | ||
|
|
55d6fcc350 | ||
|
|
9ff39503e9 | ||
|
|
f96c181afd | ||
|
|
f9b75a09df | ||
|
|
6111ed79b1 | ||
|
|
4cf2322b7f | ||
|
|
2c6fcc5dc1 | ||
|
|
81ee8541ab | ||
|
|
5b3550ab9f | ||
|
|
4fabce58d8 | ||
|
|
da7edb5f5c | ||
|
|
bf0f85e37f | ||
|
|
7b52160bff | ||
|
|
fde97ec4a7 | ||
|
|
ea7ec60f51 | ||
|
|
6667856ba5 | ||
|
|
13b2cf50ae | ||
|
|
93b0abfce9 | ||
|
|
f7e4c47113 | ||
|
|
509e43d6f8 | ||
|
|
e693192e06 | ||
|
|
ec27759f90 | ||
|
|
9c938eec73 | ||
|
|
238b907dd8 | ||
|
|
c16d8c6db8 | ||
|
|
9856e3b798 | ||
|
|
1d089272c8 | ||
|
|
c30b1130ee | ||
|
|
40ca222d09 | ||
|
|
0ecccbfd17 | ||
|
|
3f4862ced6 | ||
|
|
1574e2457b | ||
|
|
af33212f77 | ||
|
|
4eb82e8c04 | ||
|
|
a45f0aac90 | ||
|
|
eb4afdca65 | ||
|
|
9391749577 | ||
|
|
36a25660e9 | ||
|
|
d9fe722da1 | ||
|
|
da722e7db9 | ||
|
|
75a4dcbce8 | ||
|
|
3a179fcd34 | ||
|
|
ad22fe9fe7 | ||
|
|
6d622d91be | ||
|
|
aa884b003e | ||
|
|
e0f77940f9 | ||
|
|
3a1718f62b | ||
|
|
f7f9d3e5b9 | ||
|
|
68501d7799 | ||
|
|
f8a987b135 | ||
|
|
dfea6780d9 | ||
|
|
2ac8dd6361 | ||
|
|
dd0945b9ca | ||
|
|
1b05d5dd8e | ||
|
|
6923cc4a6a | ||
|
|
3feb69e63c | ||
|
|
6723792fbb | ||
|
|
3e36069f41 | ||
|
|
6a4ca92a6c | ||
|
|
3ec34ee3dd | ||
|
|
2e5c2d5e98 | ||
|
|
4dbe17d4f1 | ||
|
|
f18776cb49 | ||
|
|
429aa24275 | ||
|
|
741c9d3c63 | ||
|
|
419983c0f1 | ||
|
|
a59c80e076 | ||
|
|
55981205da | ||
|
|
c1e6037bda | ||
|
|
8e816a9283 | ||
|
|
d165c6b15a | ||
|
|
9111005165 | ||
|
|
3ceac25fb5 | ||
|
|
8ec771d5be | ||
|
|
659e5653bc | ||
|
|
3ff6de261c | ||
|
|
25dae77fcd | ||
|
|
68daadcb56 | ||
|
|
c9b1bb0285 | ||
|
|
ac5809e757 | ||
|
|
0db209a636 | ||
|
|
6c65f4acd1 | ||
|
|
3d447e8b12 | ||
|
|
f8807144d4 | ||
|
|
ebb4c8a724 | ||
|
|
893f232b2f | ||
|
|
a6aaf5429c | ||
|
|
4ef239a086 | ||
|
|
9362368fd3 | ||
|
|
b35e010e2a | ||
|
|
cc35e6a019 | ||
|
|
3281888160 | ||
|
|
c6d0ae892e | ||
|
|
df67ae9cbe | ||
|
|
ebe20efb29 | ||
|
|
b03b9b9017 | ||
|
|
73258c6193 | ||
|
|
dfe3fb8ed3 | ||
|
|
cd6bfb3f69 | ||
|
|
ba417d80b1 | ||
|
|
40eb8b93e1 | ||
|
|
6e6bd1e171 | ||
|
|
81ee2d2332 | ||
|
|
85974e9acd | ||
|
|
864c098701 | ||
|
|
cfbaf81ef8 | ||
|
|
87a791fdb9 | ||
|
|
ada7cca10d | ||
|
|
52db0f23a6 | ||
|
|
60388f7f03 | ||
|
|
53ed1c912b | ||
|
|
5f7ab83de4 | ||
|
|
05d2f70529 | ||
|
|
f950de95ba | ||
|
|
a4e5a72c36 | ||
|
|
03324d4277 | ||
|
|
e53580cb68 | ||
|
|
332ebe36c3 | ||
|
|
5013d64b28 | ||
|
|
767a81f930 | ||
|
|
78046dac8b | ||
|
|
95168b8267 | ||
|
|
c264e9c364 | ||
|
|
856e1e2948 | ||
|
|
bef4fdfc4b | ||
|
|
095a1ab041 | ||
|
|
71e578eac9 | ||
|
|
4380727727 | ||
|
|
392d46933b | ||
|
|
2bc0b46ff4 | ||
|
|
09f522f0aa | ||
|
|
d82bd430f6 | ||
|
|
49800a00bd | ||
|
|
f9dcd97936 | ||
|
|
d763c11a6d | ||
|
|
b1202ac6db | ||
|
|
d469d7d441 | ||
|
|
48dc520fb8 | ||
|
|
668d5a76d5 | ||
|
|
b9c1f10016 | ||
|
|
8a0c86cbdb | ||
|
|
7f86fe3f61 | ||
|
|
a32cf70d7e | ||
|
|
a607f33552 | ||
|
|
350a32274a | ||
|
|
27c99b46cb | ||
|
|
1d6e3d477b | ||
|
|
efbb973393 | ||
|
|
45bc7a6a9d | ||
|
|
088ebb967f | ||
|
|
bcf740f98a | ||
|
|
6b80fff2bb | ||
|
|
2e63fedb76 | ||
|
|
5a9f4e5c60 | ||
|
|
d0a48a09e2 | ||
|
|
c0a21e7025 | ||
|
|
10cc15aabe | ||
|
|
adf7681100 | ||
|
|
0237905b96 | ||
|
|
e8aa79bab6 | ||
|
|
4ff5783e59 | ||
|
|
dcfeb52983 | ||
|
|
46790e57e9 | ||
|
|
4bc3fa0826 | ||
|
|
88cfb979be | ||
|
|
32b5db754e | ||
|
|
f33f8ca109 | ||
|
|
598d63db63 | ||
|
|
38bff1b372 | ||
|
|
e8c9b21f20 | ||
|
|
6d3fc63658 | ||
|
|
ee4437ff32 | ||
|
|
7a4aa68706 | ||
|
|
f00380d285 | ||
|
|
c00d4885c6 | ||
|
|
70f4722356 | ||
|
|
8898bf7ca4 | ||
|
|
e5b13b767e | ||
|
|
3181c68cbb | ||
|
|
c3c9003dbb | ||
|
|
921b98066d | ||
|
|
c5b4cc80cc | ||
|
|
0bccd1d578 | ||
|
|
91db82c138 | ||
|
|
0eb97086fc | ||
|
|
5b34636afa | ||
|
|
f1138b9a55 | ||
|
|
23ff6dbba4 | ||
|
|
b457923970 | ||
|
|
66e4a5a64e | ||
|
|
6c25e64658 | ||
|
|
f2fd0f8f00 | ||
|
|
44cdde5422 | ||
|
|
88235dc618 | ||
|
|
4d2b671d7b | ||
|
|
8098031eac | ||
|
|
74c882d9d0 | ||
|
|
80636fec43 | ||
|
|
a8ad74aef3 | ||
|
|
e2e2b7934e | ||
|
|
28c802f399 | ||
|
|
bcfa63aa4e | ||
|
|
d40feafb01 | ||
|
|
2a8473891b | ||
|
|
a4e3451d5c | ||
|
|
53a7c2885b | ||
|
|
f354507d42 | ||
|
|
f17e1def32 | ||
|
|
3183e8b7d4 | ||
|
|
9d2b9ef2d4 | ||
|
|
733e5cd876 | ||
|
|
4ee4f7bcb3 | ||
|
|
da7ecda9ea | ||
|
|
1f11d4fb1a | ||
|
|
b308503ab5 | ||
|
|
3b10de4a28 | ||
|
|
6ce1de476a | ||
|
|
d9b0848a61 | ||
|
|
46dd3b8166 | ||
|
|
eca07be072 | ||
|
|
165d57b88e | ||
|
|
28c44f7e5a | ||
|
|
39d5bdff4b | ||
|
|
b9f8480b2f | ||
|
|
58b30d678a | ||
|
|
408cdaf5e0 | ||
|
|
cae23cde09 | ||
|
|
702fb2562c | ||
|
|
785d0b60b6 | ||
|
|
67ab9dc4d0 | ||
|
|
77494cb7df | ||
|
|
08f8856d6c | ||
|
|
79a4c1544d | ||
|
|
c0a35141e6 | ||
|
|
221bb64aeb | ||
|
|
2555dba188 | ||
|
|
6355ed6ae7 | ||
|
|
1864e8c863 | ||
|
|
61d0d66dae | ||
|
|
86522f1b3e | ||
|
|
dc32705bc9 | ||
|
|
1eaf5c31d3 | ||
|
|
677b19e22e | ||
|
|
8e248ae045 | ||
|
|
0acefd5c08 | ||
|
|
0331931f56 | ||
|
|
01e2c9cc21 | ||
|
|
4acb645f04 | ||
|
|
ef664039ac | ||
|
|
993422c6af | ||
|
|
c950d59047 | ||
|
|
cc726e0200 | ||
|
|
3d99dc78db | ||
|
|
95c3a8b805 | ||
|
|
f1bb5870ce | ||
|
|
540407e193 | ||
|
|
027d43b5ea | ||
|
|
729a6eda23 | ||
|
|
cbbd21e2e5 | ||
|
|
e7d45ca617 | ||
|
|
0ddfdb55d3 | ||
|
|
fc439455a7 | ||
|
|
c0fc02769b | ||
|
|
068ac68496 | ||
|
|
7da6a22df2 | ||
|
|
e37aeb6e6a | ||
|
|
eeb0d2b8e0 | ||
|
|
bf8c866bf7 | ||
|
|
75354b0002 | ||
|
|
4eb4d97d51 | ||
|
|
b1b82977ec | ||
|
|
f6262460ff | ||
|
|
560a610384 | ||
|
|
0308b2ff98 | ||
|
|
5b92d49be7 | ||
|
|
0386d0ae09 | ||
|
|
28bec57e1d | ||
|
|
aaa31f02af | ||
|
|
ff609a52c1 | ||
|
|
1e30793f0a | ||
|
|
5268eb479d | ||
|
|
a4eba2e6e9 | ||
|
|
0f30115205 | ||
|
|
ae500ea01d | ||
|
|
087479d459 | ||
|
|
6e2379a28c | ||
|
|
262fa184fd | ||
|
|
9a7e1c154d | ||
|
|
5bf9193dfa | ||
|
|
180fb3f39d | ||
|
|
7e6b7314f4 | ||
|
|
a262508fb8 | ||
|
|
80ff24b65a | ||
|
|
012aa67e42 | ||
|
|
0a1f12a583 | ||
|
|
f17dc812d0 | ||
|
|
1854d85ccc | ||
|
|
2c4d1fb8b4 | ||
|
|
d8fa7cf65d | ||
|
|
7d8d360138 | ||
|
|
d80880350d | ||
|
|
b693ed0dbd | ||
|
|
83f961a7c2 | ||
|
|
a093917db1 | ||
|
|
52716db649 | ||
|
|
9ca4b464ea | ||
|
|
204a31b6bb | ||
|
|
813d287a09 | ||
|
|
4dd9f33eba | ||
|
|
5953378a12 | ||
|
|
b419eed295 | ||
|
|
52deb7f352 | ||
|
|
a4f3aecbaa | ||
|
|
49ff6a852a | ||
|
|
7f537d2e98 | ||
|
|
753443b16f | ||
|
|
33c63be980 | ||
|
|
b6efca42b4 | ||
|
|
fa6eadc39a | ||
|
|
8789acefa6 | ||
|
|
0e280017e6 | ||
|
|
17e8322c29 | ||
|
|
96eda740cd | ||
|
|
fa84612357 | ||
|
|
cf1f63eda3 | ||
|
|
9704f5ce89 | ||
|
|
0eaec2af82 | ||
|
|
398d35dc97 | ||
|
|
5efeaae093 | ||
|
|
cb2dd34a5e | ||
|
|
7112a706b8 | ||
|
|
025a47d01f | ||
|
|
13f89fdb8f | ||
|
|
cc78d50ef6 | ||
|
|
a8985b1849 | ||
|
|
6a1552f65c | ||
|
|
776091cc23 | ||
|
|
f385524f48 | ||
|
|
350982e636 | ||
|
|
5854455815 | ||
|
|
9ecaf618db | ||
|
|
95b667d21e | ||
|
|
a0b689c140 | ||
|
|
ea52ed41be | ||
|
|
5a50d54fda | ||
|
|
35d118b0c4 | ||
|
|
ea7c213f5d | ||
|
|
70dd6dd394 | ||
|
|
049510afbd | ||
|
|
c120447fd0 | ||
|
|
feb1f36126 | ||
|
|
d6ef47bb2d | ||
|
|
50fd416d49 | ||
|
|
aef6904247 | ||
|
|
0bf40faf95 | ||
|
|
c90987c4b0 | ||
|
|
0e08655407 | ||
|
|
427887db9c | ||
|
|
a718622498 | ||
|
|
4e83107d79 | ||
|
|
04b6e72820 | ||
|
|
501a2539c7 | ||
|
|
6a9856d480 | ||
|
|
2c8d42d997 | ||
|
|
9c237f0bfb | ||
|
|
63bfe76720 | ||
|
|
99d7ff47c4 | ||
|
|
3ff0eb3065 | ||
|
|
4d2b265dc4 | ||
|
|
1854245bd3 | ||
|
|
4d07034930 | ||
|
|
98031173b6 | ||
|
|
e8e474597c | ||
|
|
382758790c | ||
|
|
c33920f59d | ||
|
|
33f004d4b6 | ||
|
|
8963b536ee | ||
|
|
51455e2a1e | ||
|
|
30d6a26e3e | ||
|
|
cd4fabd11b | ||
|
|
9a8b8f26ac | ||
|
|
2f73b16b57 | ||
|
|
df9952c291 | ||
|
|
ee946d8128 | ||
|
|
ec8f2e078e | ||
|
|
335f46122b | ||
|
|
73eae191e9 | ||
|
|
14e823e938 | ||
|
|
2fbd462e6e | ||
|
|
e1cc98d448 | ||
|
|
0ce64962d4 | ||
|
|
338229193f | ||
|
|
57644a4be8 | ||
|
|
da2099137a | ||
|
|
09bc8d9ca4 | ||
|
|
d95f724303 | ||
|
|
c413c3ed8f | ||
|
|
5f56be0ad4 | ||
|
|
ef441d5cff | ||
|
|
16a188c524 | ||
|
|
50c40a8d99 | ||
|
|
4114c8715c | ||
|
|
ced5fdbe70 | ||
|
|
b16aa81e0d | ||
|
|
b44971668c | ||
|
|
0ff4c284e2 | ||
|
|
e8db95be16 | ||
|
|
69c2dd53ad | ||
|
|
14a910bd64 | ||
|
|
52f97ffdc9 | ||
|
|
a1e87f6cd9 | ||
|
|
c2fc41dcd5 | ||
|
|
b62c7943e7 | ||
|
|
64caeeb12d | ||
|
|
e8ac4a1e99 | ||
|
|
19c8654195 | ||
|
|
00d7aed797 | ||
|
|
4477132448 | ||
|
|
eaeea45ace | ||
|
|
e404bf33b1 | ||
|
|
79a7edea5e | ||
|
|
2b05fe2859 | ||
|
|
f8996f0a90 | ||
|
|
eb04cdac41 | ||
|
|
125938c7a1 | ||
|
|
ec1260d8aa | ||
|
|
9eabbe2e76 | ||
|
|
5f35c579e2 | ||
|
|
99a23bdc8f | ||
|
|
d914a08896 | ||
|
|
ceccc30cb8 | ||
|
|
3366a71155 | ||
|
|
cd67804412 | ||
|
|
4a95db6013 | ||
|
|
8bf552ae25 | ||
|
|
ccd0c2382f | ||
|
|
d74663bf53 | ||
|
|
020ee56f25 | ||
|
|
87b295bc3d | ||
|
|
b9b1e92788 | ||
|
|
4000705701 | ||
|
|
673dbeee09 | ||
|
|
5288041782 | ||
|
|
4273fa9ccf | ||
|
|
01bcb9dff9 | ||
|
|
101f86ad1f | ||
|
|
2575dc2db0 | ||
|
|
b4e6f128d7 | ||
|
|
7d5e6718dc | ||
|
|
072aa7569c | ||
|
|
62871283e2 | ||
|
|
0f1dd24f97 | ||
|
|
995f551e80 | ||
|
|
15facd8cfd | ||
|
|
57bd47a446 | ||
|
|
0568c943ab | ||
|
|
b1aaa8570e | ||
|
|
3b2aa7e91d | ||
|
|
997aacf7f0 | ||
|
|
3183978c6b | ||
|
|
6a0b20456f | ||
|
|
8841112b07 | ||
|
|
16dbac6026 | ||
|
|
9b6d03c497 | ||
|
|
d3ea044619 | ||
|
|
364355c8e1 | ||
|
|
88c4e95428 | ||
|
|
9403f6ced5 | ||
|
|
56fe84e516 | ||
|
|
69d1381ba3 | ||
|
|
ccec8c4792 |
57
.github/guidelines-check.yml
vendored
@@ -1,57 +0,0 @@
|
||||
#
|
||||
# This file is intentionally in the wrong dir, will move and add later....
|
||||
#
|
||||
|
||||
name: Guidelines Check
|
||||
|
||||
on:
|
||||
# Disabled - uncomment to re-enable
|
||||
# pull_request_target:
|
||||
# types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
check-guidelines:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install opencode
|
||||
run: curl -fsSL https://opencode.ai/install | bash
|
||||
|
||||
- name: Check PR guidelines compliance
|
||||
env:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }'
|
||||
run: |
|
||||
opencode run -m anthropic/claude-sonnet-4-20250514 "A new pull request has been created: '${{ github.event.pull_request.title }}'
|
||||
|
||||
<pr-number>
|
||||
${{ github.event.pull_request.number }}
|
||||
</pr-number>
|
||||
|
||||
<pr-description>
|
||||
${{ github.event.pull_request.body }}
|
||||
</pr-description>
|
||||
|
||||
Please check all the code changes in this pull request against the guidelines in AGENTS.md file in this repository. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do
|
||||
|
||||
Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block.
|
||||
|
||||
Command MUST be like this.
|
||||
```
|
||||
gh api \
|
||||
--method POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments \
|
||||
-f 'body=[summary of issue]' -f 'commit_id=${{ github.event.pull_request.head.sha }}' -f 'path=[path-to-file]' -F "line=[line]" -f 'side=RIGHT'
|
||||
```
|
||||
|
||||
Only create comments for actual violations. If the code follows all guidelines, don't run any gh commands."
|
||||
2
.github/workflows/auto-label-tui.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
auto-label:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
2
.github/workflows/deploy.yml
vendored
@@ -11,7 +11,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
5
.github/workflows/duplicate-issues.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
check-duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
@@ -55,4 +55,7 @@ jobs:
|
||||
|
||||
Feel free to ignore if none of these address your specific case.'
|
||||
|
||||
Additionally, if the issue mentions keybinds, keyboard shortcuts, or key bindings, please add a comment mentioning the pinned keybinds issue #4997:
|
||||
'For keybind-related issues, please also check our pinned keybinds documentation: #4997'
|
||||
|
||||
If no clear duplicates are found, do not comment."
|
||||
|
||||
5
.github/workflows/format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -18,6 +18,8 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
ref: ${{ github.event.pull_request.head.ref || github.ref_name }}
|
||||
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
@@ -27,3 +29,4 @@ jobs:
|
||||
./script/format.ts
|
||||
env:
|
||||
CI: true
|
||||
PUSH_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}
|
||||
|
||||
2
.github/workflows/notify-discord.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Send nicely-formatted embed to Discord
|
||||
uses: SethCohen/github-releases-to-discord@v1
|
||||
|
||||
8
.github/workflows/opencode.yml
vendored
@@ -3,6 +3,8 @@ name: opencode
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
opencode:
|
||||
@@ -11,7 +13,7 @@ jobs:
|
||||
startsWith(github.event.comment.body, '/oc') ||
|
||||
contains(github.event.comment.body, ' /opencode') ||
|
||||
startsWith(github.event.comment.body, '/opencode')
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
@@ -21,9 +23,11 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: Run opencode
|
||||
uses: sst/opencode/github@latest
|
||||
env:
|
||||
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
||||
with:
|
||||
model: opencode/glm-4.6
|
||||
model: opencode/claude-haiku-4-5
|
||||
|
||||
2
.github/workflows/publish-github-action.yml
vendored
@@ -14,7 +14,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/publish-vscode.yml
vendored
@@ -13,7 +13,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
103
.github/workflows/publish.yml
vendored
@@ -25,7 +25,8 @@ permissions:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
if: github.repository == 'sst/opencode' && github.ref == 'refs/heads/dev'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -79,3 +80,103 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||
AUR_KEY: ${{ secrets.AUR_KEY }}
|
||||
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
||||
|
||||
publish-tauri:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
settings:
|
||||
- host: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- host: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
- host: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
- host: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
runs-on: ${{ matrix.settings.host }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: apple-actions/import-codesign-certs@v2
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
with:
|
||||
keychain: build
|
||||
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
|
||||
- name: Verify Certificate
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: |
|
||||
CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application")
|
||||
CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
|
||||
echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
|
||||
echo "Certificate imported."
|
||||
|
||||
- name: Setup Apple API Key
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: |
|
||||
echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8
|
||||
|
||||
- run: git fetch --force --tags
|
||||
|
||||
- uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: startsWith(matrix.settings.host, 'ubuntu')
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.settings.target }}
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: packages/tauri/src-tauri
|
||||
shared-key: ${{ matrix.settings.target }}
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
cd packages/tauri
|
||||
bun ./scripts/prepare.ts
|
||||
env:
|
||||
OPENCODE_BUMP: ${{ inputs.bump }}
|
||||
OPENCODE_VERSION: ${{ inputs.version }}
|
||||
OPENCODE_CHANNEL: latest
|
||||
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||
AUR_KEY: ${{ secrets.AUR_KEY }}
|
||||
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
||||
RUST_TARGET: ${{ matrix.settings.target }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
# Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released
|
||||
- run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage
|
||||
if: startsWith(matrix.settings.host, 'ubuntu')
|
||||
|
||||
- name: Build and upload artifacts
|
||||
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_BUNDLER_NEW_APPIMAGE_FORMAT: true
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }}
|
||||
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
|
||||
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
|
||||
APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8
|
||||
with:
|
||||
projectPath: packages/tauri
|
||||
uploadWorkflowArtifacts: true
|
||||
tauriScript: ${{ (startsWith(matrix.settings.host, 'ubuntu') && 'cargo tauri') || '' }}
|
||||
args: --target ${{ matrix.settings.target }}
|
||||
updaterJsonPreferNsis: true
|
||||
# releaseId: TODO
|
||||
|
||||
79
.github/workflows/review.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: Guidelines Check
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
check-guidelines:
|
||||
if: |
|
||||
github.event.issue.pull_request &&
|
||||
startsWith(github.event.comment.body, '/review') &&
|
||||
contains(fromJson('["OWNER","MEMBER"]'), github.event.comment.author_association)
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Get PR number
|
||||
id: pr-number
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
|
||||
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install opencode
|
||||
run: curl -fsSL https://opencode.ai/install | bash
|
||||
|
||||
- name: Get PR details
|
||||
id: pr-details
|
||||
run: |
|
||||
gh api /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }} > pr_data.json
|
||||
echo "title=$(jq -r .title pr_data.json)" >> $GITHUB_OUTPUT
|
||||
echo "sha=$(jq -r .head.sha pr_data.json)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check PR guidelines compliance
|
||||
env:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }'
|
||||
PR_TITLE: ${{ steps.pr-details.outputs.title }}
|
||||
run: |
|
||||
PR_BODY=$(jq -r .body pr_data.json)
|
||||
opencode run -m anthropic/claude-opus-4-5 "A new pull request has been created: '${PR_TITLE}'
|
||||
|
||||
<pr-number>
|
||||
${{ steps.pr-number.outputs.number }}
|
||||
</pr-number>
|
||||
|
||||
<pr-description>
|
||||
$PR_BODY
|
||||
</pr-description>
|
||||
|
||||
Please check all the code changes in this pull request against the style guide, also look for any bugs if they exist. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do
|
||||
|
||||
When critiquing code against the style guide, be sure that the code is ACTUALLY in violation, don't complain about else statements if they already use early returns there. You may complain about excessive nesting though, regardless of else statement usage.
|
||||
When critiquing code style don't be a zealot, we don't like "let" statements but sometimes they are the simpliest option, if someone does a bunch of nesting with let, they should consider using iife (see packages/opencode/src/util.iife.ts)
|
||||
|
||||
Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block.
|
||||
|
||||
Command MUST be like this.
|
||||
\`\`\`
|
||||
gh api \
|
||||
--method POST \
|
||||
-H \"Accept: application/vnd.github+json\" \
|
||||
-H \"X-GitHub-Api-Version: 2022-11-28\" \
|
||||
/repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }}/comments \
|
||||
-f 'body=[summary of issue]' -f 'commit_id=${{ steps.pr-details.outputs.sha }}' -f 'path=[path-to-file]' -F \"line=[line]\" -f 'side=RIGHT'
|
||||
\`\`\`
|
||||
|
||||
Only create comments for actual violations. If the code follows all guidelines, comment on the issue using gh cli: 'lgtm' AND NOTHING ELSE!!!!."
|
||||
39
.github/workflows/sdk.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: sdk
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- production
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- production
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
format:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
bun ./packages/sdk/js/script/build.ts
|
||||
(cd packages/opencode && bun dev generate > ../sdk/openapi.json)
|
||||
if [ -z "$(git status --porcelain)" ]; then
|
||||
echo "No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add -A
|
||||
git commit -m "chore: regen sdk"
|
||||
git push --no-verify
|
||||
env:
|
||||
CI: true
|
||||
7
.github/workflows/snapshot.yml
vendored
@@ -1,17 +1,20 @@
|
||||
name: snapshot
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- fix-snapshot-2
|
||||
- test-bedrock
|
||||
- v0
|
||||
- otui-diffs
|
||||
- snapshot-*
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/stats.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
stats:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
|
||||
2
.github/workflows/sync-zed-extension.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
zed:
|
||||
name: Release Zed Extension
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
8
.github/workflows/test.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -28,9 +28,3 @@ jobs:
|
||||
bun turbo test
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Check SDK is up to date
|
||||
run: |
|
||||
bun ./packages/sdk/js/script/build.ts
|
||||
git diff --exit-code packages/sdk/js/src/gen packages/sdk/js/dist
|
||||
continue-on-error: false
|
||||
|
||||
2
.github/workflows/typecheck.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
20
.github/workflows/update-nix-hashes.yml
vendored
@@ -18,7 +18,8 @@ on:
|
||||
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
env:
|
||||
SYSTEM: x86_64-linux
|
||||
|
||||
@@ -29,6 +30,7 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.head_ref || github.ref_name }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
|
||||
- name: Setup Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v20
|
||||
@@ -41,12 +43,16 @@ jobs:
|
||||
- name: Update flake.lock
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "📦 Updating flake.lock..."
|
||||
nix flake update
|
||||
echo "✅ flake.lock updated successfully"
|
||||
|
||||
- name: Update node_modules hash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "🔄 Updating node_modules hash..."
|
||||
nix/scripts/update-hashes.sh
|
||||
echo "✅ node_modules hash updated successfully"
|
||||
|
||||
- name: Commit hash changes
|
||||
env:
|
||||
@@ -54,6 +60,8 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "🔍 Checking for changes in tracked Nix files..."
|
||||
|
||||
summarize() {
|
||||
local status="$1"
|
||||
{
|
||||
@@ -71,16 +79,24 @@ jobs:
|
||||
FILES=(flake.lock flake.nix nix/node-modules.nix nix/hashes.json)
|
||||
STATUS="$(git status --short -- "${FILES[@]}" || true)"
|
||||
if [ -z "$STATUS" ]; then
|
||||
echo "✅ No changes detected. Hashes are already up to date."
|
||||
summarize "no changes"
|
||||
echo "No changes to tracked Nix files. Hashes are already up to date."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📝 Changes detected:"
|
||||
echo "$STATUS"
|
||||
echo "🔗 Staging files..."
|
||||
git add "${FILES[@]}"
|
||||
echo "💾 Committing changes..."
|
||||
git commit -m "Update Nix flake.lock and hashes"
|
||||
echo "✅ Changes committed"
|
||||
|
||||
BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}"
|
||||
echo "🌳 Pulling latest from branch: $BRANCH"
|
||||
git pull --rebase origin "$BRANCH"
|
||||
echo "🚀 Pushing changes to branch: $BRANCH"
|
||||
git push origin HEAD:"$BRANCH"
|
||||
echo "✅ Changes pushed successfully"
|
||||
|
||||
summarize "committed $(git rev-parse --short HEAD)"
|
||||
|
||||
2
.gitignore
vendored
@@ -6,7 +6,6 @@ node_modules
|
||||
.idea
|
||||
.vscode
|
||||
*~
|
||||
openapi.json
|
||||
playground
|
||||
tmp
|
||||
dist
|
||||
@@ -18,3 +17,4 @@ refs
|
||||
Session.vim
|
||||
opencode.json
|
||||
a.out
|
||||
target
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
#!/bin/sh
|
||||
# Check if bun version matches package.json
|
||||
EXPECTED_VERSION=$(grep '"packageManager"' package.json | sed 's/.*"bun@\([^"]*\)".*/\1/')
|
||||
CURRENT_VERSION=$(bun --version)
|
||||
if [ "$CURRENT_VERSION" != "$EXPECTED_VERSION" ]; then
|
||||
echo "Error: Bun version $CURRENT_VERSION does not match expected version $EXPECTED_VERSION from package.json"
|
||||
exit 1
|
||||
fi
|
||||
bun typecheck
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
description: Git commit and push
|
||||
subtask: true
|
||||
description: git commit and push
|
||||
---
|
||||
|
||||
commit and push
|
||||
@@ -22,3 +21,6 @@ WHAT was done.
|
||||
|
||||
do not do generic messages like "improved agent experience" be very specific
|
||||
about what user facing changes were made
|
||||
|
||||
if there are changes do a git pull --rebase
|
||||
if there are conflicts DO NOT FIX THEM. notify me and I will fix them
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
description: hello world iaosd ioasjdoiasjd oisadjoisajd osiajd oisaj dosaij dsoajsajdaijdoisa jdoias jdoias jdoia jois jo jdois jdoias jdoias j djoasdj
|
||||
---
|
||||
|
||||
hey there $ARGUMENTS
|
||||
|
||||
!`ls`
|
||||
check out @README.md
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: "Find issue(s) on github"
|
||||
description: "find issue(s) on github"
|
||||
model: opencode/claude-haiku-4-5
|
||||
---
|
||||
|
||||
|
||||
15
.opencode/command/rmslop.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
description: Remove AI code slop
|
||||
---
|
||||
|
||||
Check the diff against dev, and remove all AI generated slop introduced in this branch.
|
||||
|
||||
This includes:
|
||||
|
||||
- Extra comments that a human wouldn't add or is inconsistent with the rest of the file
|
||||
- Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
|
||||
- Casts to any to get around type issues
|
||||
- Any other style that is inconsistent with the file
|
||||
- Unnecessary emoji usage
|
||||
|
||||
Report at the end with only a 1-3 sentence summary of what you changed
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Spellcheck all markdown file changes
|
||||
description: spellcheck all markdown file changes
|
||||
---
|
||||
|
||||
Look at all the unstaged changes to markdown (.md, .mdx) files, pull out the lines that have changed, and check for spelling and grammar errors.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"plugin": ["opencode-openai-codex-auth"],
|
||||
"enterprise": {
|
||||
"url": "http://localhost:3000",
|
||||
},
|
||||
// "enterprise": {
|
||||
// "url": "https://enterprise.dev.opencode.ai",
|
||||
// },
|
||||
"instructions": ["STYLE_GUIDE.md"],
|
||||
"provider": {
|
||||
"opencode": {
|
||||
"options": {
|
||||
@@ -11,4 +12,17 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
"mcp": {
|
||||
"exa": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.exa.ai/mcp",
|
||||
},
|
||||
"morph": {
|
||||
"type": "local",
|
||||
"command": ["bunx", "@morphllm/morphmcp"],
|
||||
"environment": {
|
||||
"ENABLED_TOOLS": "warp_grep",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
1
.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
sst-env.d.ts
|
||||
13
AGENTS.md
@@ -1,16 +1,3 @@
|
||||
## IMPORTANT
|
||||
|
||||
- Try to keep things in one function unless composable or reusable
|
||||
- DO NOT do unnecessary destructuring of variables
|
||||
- DO NOT use `else` statements unless necessary
|
||||
- DO NOT use `try`/`catch` if it can be avoided
|
||||
- AVOID `try`/`catch` where possible
|
||||
- AVOID `else` statements
|
||||
- AVOID using `any` type
|
||||
- AVOID `let` statements
|
||||
- PREFER single word variable names where possible
|
||||
- Use as many bun apis as possible like Bun.file()
|
||||
|
||||
## Debugging
|
||||
|
||||
- To test opencode in the `packages/opencode` directory you can run `bun dev`
|
||||
|
||||
@@ -42,6 +42,8 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you
|
||||
> [!NOTE]
|
||||
> After touching `packages/opencode/src/server/server.ts`, run "./packages/sdk/js/script/build.ts" to regenerate the JS sdk.
|
||||
|
||||
Please try to follow the [style guide](./STYLE_GUIDE.md)
|
||||
|
||||
### Setting up a Debugger
|
||||
|
||||
Bun debugging is currently rough around the edges. We hope this guide helps you get set up and avoid some pain points.
|
||||
|
||||
314
STATS.md
@@ -1,152 +1,166 @@
|
||||
# Download Stats
|
||||
|
||||
| Date | GitHub Downloads | npm Downloads | Total |
|
||||
| ---------- | ----------------- | ----------------- | ------------------- |
|
||||
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
|
||||
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
|
||||
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
|
||||
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
|
||||
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
|
||||
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
|
||||
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
|
||||
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
|
||||
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
|
||||
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
|
||||
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
|
||||
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
|
||||
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
|
||||
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
|
||||
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
|
||||
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
|
||||
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
|
||||
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
|
||||
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
|
||||
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
|
||||
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
|
||||
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
|
||||
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
|
||||
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
|
||||
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
|
||||
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
|
||||
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
|
||||
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
|
||||
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
|
||||
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
|
||||
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
|
||||
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
|
||||
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
|
||||
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
|
||||
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
|
||||
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
|
||||
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
|
||||
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
|
||||
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
|
||||
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
|
||||
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
|
||||
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
|
||||
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
|
||||
| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) |
|
||||
| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) |
|
||||
| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) |
|
||||
| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) |
|
||||
| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) |
|
||||
| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) |
|
||||
| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) |
|
||||
| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) |
|
||||
| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) |
|
||||
| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) |
|
||||
| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) |
|
||||
| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) |
|
||||
| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) |
|
||||
| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) |
|
||||
| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) |
|
||||
| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) |
|
||||
| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) |
|
||||
| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) |
|
||||
| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) |
|
||||
| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) |
|
||||
| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) |
|
||||
| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) |
|
||||
| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) |
|
||||
| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) |
|
||||
| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) |
|
||||
| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) |
|
||||
| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) |
|
||||
| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) |
|
||||
| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) |
|
||||
| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) |
|
||||
| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) |
|
||||
| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) |
|
||||
| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) |
|
||||
| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) |
|
||||
| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) |
|
||||
| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) |
|
||||
| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) |
|
||||
| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) |
|
||||
| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) |
|
||||
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
|
||||
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
|
||||
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
|
||||
| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) |
|
||||
| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) |
|
||||
| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) |
|
||||
| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) |
|
||||
| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) |
|
||||
| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) |
|
||||
| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) |
|
||||
| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) |
|
||||
| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) |
|
||||
| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) |
|
||||
| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) |
|
||||
| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) |
|
||||
| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) |
|
||||
| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) |
|
||||
| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) |
|
||||
| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) |
|
||||
| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) |
|
||||
| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) |
|
||||
| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) |
|
||||
| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) |
|
||||
| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) |
|
||||
| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) |
|
||||
| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) |
|
||||
| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) |
|
||||
| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) |
|
||||
| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) |
|
||||
| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) |
|
||||
| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) |
|
||||
| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) |
|
||||
| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) |
|
||||
| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) |
|
||||
| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) |
|
||||
| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) |
|
||||
| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) |
|
||||
| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) |
|
||||
| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) |
|
||||
| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) |
|
||||
| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) |
|
||||
| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) |
|
||||
| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) |
|
||||
| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) |
|
||||
| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) |
|
||||
| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) |
|
||||
| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) |
|
||||
| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) |
|
||||
| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) |
|
||||
| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) |
|
||||
| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) |
|
||||
| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) |
|
||||
| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) |
|
||||
| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) |
|
||||
| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) |
|
||||
| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) |
|
||||
| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) |
|
||||
| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) |
|
||||
| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) |
|
||||
| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) |
|
||||
| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) |
|
||||
| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) |
|
||||
| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) |
|
||||
| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) |
|
||||
| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) |
|
||||
| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) |
|
||||
| Date | GitHub Downloads | npm Downloads | Total |
|
||||
| ---------- | ------------------ | ----------------- | ------------------- |
|
||||
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
|
||||
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
|
||||
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
|
||||
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
|
||||
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
|
||||
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
|
||||
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
|
||||
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
|
||||
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
|
||||
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
|
||||
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
|
||||
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
|
||||
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
|
||||
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
|
||||
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
|
||||
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
|
||||
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
|
||||
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
|
||||
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
|
||||
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
|
||||
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
|
||||
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
|
||||
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
|
||||
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
|
||||
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
|
||||
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
|
||||
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
|
||||
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
|
||||
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
|
||||
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
|
||||
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
|
||||
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
|
||||
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
|
||||
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
|
||||
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
|
||||
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
|
||||
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
|
||||
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
|
||||
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
|
||||
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
|
||||
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
|
||||
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
|
||||
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
|
||||
| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) |
|
||||
| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) |
|
||||
| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) |
|
||||
| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) |
|
||||
| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) |
|
||||
| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) |
|
||||
| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) |
|
||||
| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) |
|
||||
| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) |
|
||||
| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) |
|
||||
| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) |
|
||||
| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) |
|
||||
| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) |
|
||||
| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) |
|
||||
| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) |
|
||||
| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) |
|
||||
| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) |
|
||||
| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) |
|
||||
| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) |
|
||||
| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) |
|
||||
| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) |
|
||||
| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) |
|
||||
| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) |
|
||||
| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) |
|
||||
| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) |
|
||||
| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) |
|
||||
| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) |
|
||||
| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) |
|
||||
| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) |
|
||||
| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) |
|
||||
| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) |
|
||||
| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) |
|
||||
| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) |
|
||||
| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) |
|
||||
| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) |
|
||||
| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) |
|
||||
| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) |
|
||||
| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) |
|
||||
| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) |
|
||||
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
|
||||
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
|
||||
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
|
||||
| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) |
|
||||
| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) |
|
||||
| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) |
|
||||
| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) |
|
||||
| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) |
|
||||
| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) |
|
||||
| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) |
|
||||
| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) |
|
||||
| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) |
|
||||
| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) |
|
||||
| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) |
|
||||
| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) |
|
||||
| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) |
|
||||
| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) |
|
||||
| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) |
|
||||
| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) |
|
||||
| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) |
|
||||
| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) |
|
||||
| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) |
|
||||
| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) |
|
||||
| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) |
|
||||
| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) |
|
||||
| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) |
|
||||
| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) |
|
||||
| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) |
|
||||
| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) |
|
||||
| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) |
|
||||
| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) |
|
||||
| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) |
|
||||
| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) |
|
||||
| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) |
|
||||
| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) |
|
||||
| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) |
|
||||
| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) |
|
||||
| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) |
|
||||
| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) |
|
||||
| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) |
|
||||
| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) |
|
||||
| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) |
|
||||
| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) |
|
||||
| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) |
|
||||
| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) |
|
||||
| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) |
|
||||
| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) |
|
||||
| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) |
|
||||
| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) |
|
||||
| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) |
|
||||
| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) |
|
||||
| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) |
|
||||
| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) |
|
||||
| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) |
|
||||
| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) |
|
||||
| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) |
|
||||
| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) |
|
||||
| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) |
|
||||
| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) |
|
||||
| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) |
|
||||
| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) |
|
||||
| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) |
|
||||
| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) |
|
||||
| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) |
|
||||
| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) |
|
||||
| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) |
|
||||
| 2025-11-25 | 869,423 (+12,690) | 817,339 (+13,306) | 1,686,762 (+25,996) |
|
||||
| 2025-11-26 | 881,414 (+11,991) | 832,518 (+15,179) | 1,713,932 (+27,170) |
|
||||
| 2025-11-27 | 893,960 (+12,546) | 846,180 (+13,662) | 1,740,140 (+26,208) |
|
||||
| 2025-11-28 | 901,741 (+7,781) | 856,482 (+10,302) | 1,758,223 (+18,083) |
|
||||
| 2025-11-29 | 908,689 (+6,948) | 863,361 (+6,879) | 1,772,050 (+13,827) |
|
||||
| 2025-11-30 | 916,116 (+7,427) | 870,194 (+6,833) | 1,786,310 (+14,260) |
|
||||
| 2025-12-01 | 925,898 (+9,782) | 876,500 (+6,306) | 1,802,398 (+16,088) |
|
||||
| 2025-12-02 | 939,250 (+13,352) | 890,919 (+14,419) | 1,830,169 (+27,771) |
|
||||
| 2025-12-03 | 952,249 (+12,999) | 903,713 (+12,794) | 1,855,962 (+25,793) |
|
||||
| 2025-12-04 | 965,611 (+13,362) | 916,471 (+12,758) | 1,882,082 (+26,120) |
|
||||
| 2025-12-05 | 977,996 (+12,385) | 930,616 (+14,145) | 1,908,612 (+26,530) |
|
||||
| 2025-12-06 | 987,884 (+9,888) | 943,773 (+13,157) | 1,931,657 (+23,045) |
|
||||
| 2025-12-07 | 994,046 (+6,162) | 951,425 (+7,652) | 1,945,471 (+13,814) |
|
||||
| 2025-12-08 | 1,000,898 (+6,852) | 957,149 (+5,724) | 1,958,047 (+12,576) |
|
||||
|
||||
12
STYLE_GUIDE.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## Style Guide
|
||||
|
||||
- Try to keep things in one function unless composable or reusable
|
||||
- DO NOT do unnecessary destructuring of variables
|
||||
- DO NOT use `else` statements unless necessary
|
||||
- DO NOT use `try`/`catch` if it can be avoided
|
||||
- AVOID `try`/`catch` where possible
|
||||
- AVOID `else` statements
|
||||
- AVOID using `any` type
|
||||
- AVOID `let` statements
|
||||
- PREFER single word variable names where possible
|
||||
- Use as many bun apis as possible like Bun.file()
|
||||
6
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1763934636,
|
||||
"narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=",
|
||||
"lastModified": 1764947035,
|
||||
"narHash": "sha256-EYHSjVM4Ox4lvCXUMiKKs2vETUSL5mx+J2FfutM7T9w=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ee09932cedcef15aaf476f9343d1dea2cb77e261",
|
||||
"rev": "a672be65651c80d3f592a89b3945466584a22069",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -30,6 +30,24 @@ Leave the following comment on a GitHub PR. opencode will implement the requeste
|
||||
Delete the attachment from S3 when the note is removed /oc
|
||||
```
|
||||
|
||||
#### Review specific code lines
|
||||
|
||||
Leave a comment directly on code lines in the PR's "Files" tab. opencode will automatically detect the file, line numbers, and diff context to provide precise responses.
|
||||
|
||||
```
|
||||
[Comment on specific lines in Files tab]
|
||||
/oc add error handling here
|
||||
```
|
||||
|
||||
When commenting on specific lines, opencode receives:
|
||||
|
||||
- The exact file being reviewed
|
||||
- The specific lines of code
|
||||
- The surrounding diff context
|
||||
- Line number information
|
||||
|
||||
This allows for more targeted requests without needing to specify file paths or line numbers manually.
|
||||
|
||||
## Installation
|
||||
|
||||
Run the following command in the terminal from your GitHub repo:
|
||||
@@ -51,6 +69,8 @@ This will walk you through installing the GitHub app, creating the workflow, and
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
opencode:
|
||||
@@ -135,3 +155,9 @@ Replace the image URL `https://github.com/user-attachments/assets/xxxxxxxx` with
|
||||
```
|
||||
MOCK_EVENT='{"eventName":"issue_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"issue":{"number":4,"pull_request":{}},"comment":{"id":1,"body":"hey opencode, summarize thread"}}}'
|
||||
```
|
||||
|
||||
### PR review comment event
|
||||
|
||||
```
|
||||
MOCK_EVENT='{"eventName":"pull_request_review_comment","repo":{"owner":"sst","repo":"hello-world"},"actor":"fwang","payload":{"pull_request":{"number":7},"comment":{"id":1,"body":"hey opencode, add error handling","path":"src/components/Button.tsx","diff_hunk":"@@ -45,8 +45,11 @@\n- const handleClick = () => {\n- console.log('clicked')\n+ const handleClick = useCallback(() => {\n+ console.log('clicked')\n+ doSomething()\n+ }, [doSomething])","line":47,"original_line":45,"position":10,"commit_id":"abc123","original_commit_id":"def456"}}}'
|
||||
```
|
||||
|
||||
@@ -13,6 +13,10 @@ inputs:
|
||||
description: "Share the opencode session (defaults to true for public repos)"
|
||||
required: false
|
||||
|
||||
prompt:
|
||||
description: "Custom prompt to override the default prompt"
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
@@ -27,3 +31,4 @@ runs:
|
||||
env:
|
||||
MODEL: ${{ inputs.model }}
|
||||
SHARE: ${{ inputs.share }}
|
||||
PROMPT: ${{ inputs.prompt }}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { graphql } from "@octokit/graphql"
|
||||
import * as core from "@actions/core"
|
||||
import * as github from "@actions/github"
|
||||
import type { Context as GitHubContext } from "@actions/github/lib/context"
|
||||
import type { IssueCommentEvent } from "@octokit/webhooks-types"
|
||||
import type { IssueCommentEvent, PullRequestReviewCommentEvent } from "@octokit/webhooks-types"
|
||||
import { createOpencodeClient } from "@opencode-ai/sdk"
|
||||
import { spawn } from "node:child_process"
|
||||
|
||||
@@ -124,7 +124,7 @@ let exitCode = 0
|
||||
type PromptFiles = Awaited<ReturnType<typeof getUserPrompt>>["promptFiles"]
|
||||
|
||||
try {
|
||||
assertContextEvent("issue_comment")
|
||||
assertContextEvent("issue_comment", "pull_request_review_comment")
|
||||
assertPayloadKeyword()
|
||||
await assertOpencodeConnected()
|
||||
|
||||
@@ -241,19 +241,43 @@ function createOpencode() {
|
||||
}
|
||||
|
||||
function assertPayloadKeyword() {
|
||||
const payload = useContext().payload as IssueCommentEvent
|
||||
const payload = useContext().payload as IssueCommentEvent | PullRequestReviewCommentEvent
|
||||
const body = payload.comment.body.trim()
|
||||
if (!body.match(/(?:^|\s)(?:\/opencode|\/oc)(?=$|\s)/)) {
|
||||
throw new Error("Comments must mention `/opencode` or `/oc`")
|
||||
}
|
||||
}
|
||||
|
||||
function getReviewCommentContext() {
|
||||
const context = useContext()
|
||||
if (context.eventName !== "pull_request_review_comment") {
|
||||
return null
|
||||
}
|
||||
|
||||
const payload = context.payload as PullRequestReviewCommentEvent
|
||||
return {
|
||||
file: payload.comment.path,
|
||||
diffHunk: payload.comment.diff_hunk,
|
||||
line: payload.comment.line,
|
||||
originalLine: payload.comment.original_line,
|
||||
position: payload.comment.position,
|
||||
commitId: payload.comment.commit_id,
|
||||
originalCommitId: payload.comment.original_commit_id,
|
||||
}
|
||||
}
|
||||
|
||||
async function assertOpencodeConnected() {
|
||||
let retry = 0
|
||||
let connected = false
|
||||
do {
|
||||
try {
|
||||
await client.app.get<true>()
|
||||
await client.app.log<true>({
|
||||
body: {
|
||||
service: "github-workflow",
|
||||
level: "info",
|
||||
message: "Prepare to react to Github Workflow event",
|
||||
},
|
||||
})
|
||||
connected = true
|
||||
break
|
||||
} catch (e) {}
|
||||
@@ -383,11 +407,24 @@ async function createComment() {
|
||||
}
|
||||
|
||||
async function getUserPrompt() {
|
||||
const context = useContext()
|
||||
const payload = context.payload as IssueCommentEvent | PullRequestReviewCommentEvent
|
||||
const reviewContext = getReviewCommentContext()
|
||||
|
||||
let prompt = (() => {
|
||||
const payload = useContext().payload as IssueCommentEvent
|
||||
const body = payload.comment.body.trim()
|
||||
if (body === "/opencode" || body === "/oc") return "Summarize this thread"
|
||||
if (body.includes("/opencode") || body.includes("/oc")) return body
|
||||
if (body === "/opencode" || body === "/oc") {
|
||||
if (reviewContext) {
|
||||
return `Review this code change and suggest improvements for the commented lines:\n\nFile: ${reviewContext.file}\nLines: ${reviewContext.line}\n\n${reviewContext.diffHunk}`
|
||||
}
|
||||
return "Summarize this thread"
|
||||
}
|
||||
if (body.includes("/opencode") || body.includes("/oc")) {
|
||||
if (reviewContext) {
|
||||
return `${body}\n\nContext: You are reviewing a comment on file "${reviewContext.file}" at line ${reviewContext.line}.\n\nDiff context:\n${reviewContext.diffHunk}`
|
||||
}
|
||||
return body
|
||||
}
|
||||
throw new Error("Comments must mention `/opencode` or `/oc`")
|
||||
})()
|
||||
|
||||
|
||||
2
github/sst-env.d.ts
vendored
@@ -6,4 +6,4 @@
|
||||
/// <reference path="../sst-env.d.ts" />
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
@@ -116,7 +116,7 @@ const gatewayKv = new sst.cloudflare.Kv("GatewayKv")
|
||||
// CONSOLE
|
||||
////////////////
|
||||
|
||||
const bucket = new sst.cloudflare.Bucket("ConsoleData")
|
||||
const bucket = new sst.cloudflare.Bucket("ZenData")
|
||||
|
||||
const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID")
|
||||
const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY")
|
||||
|
||||
91
install
@@ -4,50 +4,89 @@ APP=opencode
|
||||
|
||||
MUTED='\033[0;2m'
|
||||
RED='\033[0;31m'
|
||||
ORANGE='\033[38;2;255;140;0m'
|
||||
ORANGE='\033[38;5;214m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
requested_version=${VERSION:-}
|
||||
|
||||
raw_os=$(uname -s)
|
||||
os=$(echo "$raw_os" | tr '[:upper:]' '[:lower:]')
|
||||
# Normalize various Unix-like identifiers
|
||||
case "$raw_os" in
|
||||
Darwin*) os="darwin" ;;
|
||||
Linux*) os="linux" ;;
|
||||
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
|
||||
esac
|
||||
arch=$(uname -m)
|
||||
esac
|
||||
|
||||
arch=$(uname -m)
|
||||
if [[ "$arch" == "aarch64" ]]; then
|
||||
arch="arm64"
|
||||
elif [[ "$arch" == "x86_64" ]]; then
|
||||
fi
|
||||
if [[ "$arch" == "x86_64" ]]; then
|
||||
arch="x64"
|
||||
fi
|
||||
|
||||
if [ "$os" = "linux" ]; then
|
||||
filename="$APP-$os-$arch.tar.gz"
|
||||
else
|
||||
filename="$APP-$os-$arch.zip"
|
||||
if [ "$os" = "darwin" ] && [ "$arch" = "x64" ]; then
|
||||
rosetta_flag=$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)
|
||||
if [ "$rosetta_flag" = "1" ]; then
|
||||
arch="arm64"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
case "$filename" in
|
||||
*"-linux-"*)
|
||||
[[ "$arch" == "x64" || "$arch" == "arm64" ]] || exit 1
|
||||
combo="$os-$arch"
|
||||
case "$combo" in
|
||||
linux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64)
|
||||
;;
|
||||
*"-darwin-"*)
|
||||
[[ "$arch" == "x64" || "$arch" == "arm64" ]] || exit 1
|
||||
;;
|
||||
*"-windows-"*)
|
||||
[[ "$arch" == "x64" ]] || exit 1
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"
|
||||
exit 1
|
||||
*)
|
||||
echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
archive_ext=".zip"
|
||||
if [ "$os" = "linux" ]; then
|
||||
archive_ext=".tar.gz"
|
||||
fi
|
||||
|
||||
is_musl=false
|
||||
if [ "$os" = "linux" ]; then
|
||||
if [ -f /etc/alpine-release ]; then
|
||||
is_musl=true
|
||||
fi
|
||||
|
||||
if command -v ldd >/dev/null 2>&1; then
|
||||
if ldd --version 2>&1 | grep -qi musl; then
|
||||
is_musl=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
needs_baseline=false
|
||||
if [ "$arch" = "x64" ]; then
|
||||
if [ "$os" = "linux" ]; then
|
||||
if ! grep -qi avx2 /proc/cpuinfo 2>/dev/null; then
|
||||
needs_baseline=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$os" = "darwin" ]; then
|
||||
avx2=$(sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0)
|
||||
if [ "$avx2" != "1" ]; then
|
||||
needs_baseline=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
target="$os-$arch"
|
||||
if [ "$needs_baseline" = "true" ]; then
|
||||
target="$target-baseline"
|
||||
fi
|
||||
if [ "$is_musl" = "true" ]; then
|
||||
target="$target-musl"
|
||||
fi
|
||||
|
||||
filename="$APP-$target$archive_ext"
|
||||
|
||||
|
||||
if [ "$os" = "linux" ]; then
|
||||
if ! command -v tar >/dev/null 2>&1; then
|
||||
echo -e "${RED}Error: 'tar' is required but not installed.${NC}"
|
||||
@@ -314,10 +353,10 @@ echo -e "${MUTED}█░░█ █░░█ █▀▀▀ █░░█ ${NC}█░
|
||||
echo -e "${MUTED}▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀ ${NC}▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀"
|
||||
echo -e ""
|
||||
echo -e ""
|
||||
echo -e "${MUTED}To get started, navigate to a project and run:${NC}"
|
||||
echo -e "opencode ${MUTED}Use free models${NC}"
|
||||
echo -e "opencode auth login ${MUTED}Add paid provider API keys${NC}"
|
||||
echo -e "opencode help ${MUTED}List commands and options${NC}"
|
||||
echo -e "${MUTED}OpenCode includes free models, to start:${NC}"
|
||||
echo -e ""
|
||||
echo -e "cd <project> ${MUTED}# Open directory${NC}"
|
||||
echo -e "opencode ${MUTED}# Run command${NC}"
|
||||
echo -e ""
|
||||
echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/docs"
|
||||
echo -e ""
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"nodeModules": "sha256-EikMl2CESyJpTT48CGq8xr/N+WTkvCj05N6enXQmRbI="
|
||||
"nodeModules": "sha256-IzF5XDY09Z1p/8jgYIHhE/jpKPub15KKUpV+a/aKpuc="
|
||||
}
|
||||
|
||||
@@ -113,6 +113,8 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
done
|
||||
'';
|
||||
|
||||
dontFixup = true;
|
||||
|
||||
meta = {
|
||||
description = "AI coding agent built for the terminal";
|
||||
longDescription = ''
|
||||
|
||||
14
package.json
@@ -30,16 +30,16 @@
|
||||
"@tsconfig/bun": "1.0.9",
|
||||
"@cloudflare/workers-types": "4.20251008.0",
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@pierre/precision-diffs": "0.5.4",
|
||||
"@pierre/precision-diffs": "0.6.0-beta.10",
|
||||
"@tailwindcss/vite": "4.1.11",
|
||||
"diff": "8.0.2",
|
||||
"ai": "5.0.97",
|
||||
"hono": "4.7.10",
|
||||
"hono-openapi": "1.1.1",
|
||||
"hono": "4.10.7",
|
||||
"hono-openapi": "1.1.2",
|
||||
"fuzzysort": "3.1.0",
|
||||
"luxon": "3.6.1",
|
||||
"typescript": "5.8.2",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251014.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
||||
"zod": "4.1.8",
|
||||
"remeda": "2.26.0",
|
||||
"solid-list": "0.3.0",
|
||||
@@ -63,7 +63,8 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.933.0",
|
||||
"@opencode-ai/script": "workspace:*",
|
||||
"@opencode-ai/sdk": "workspace:*"
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -85,5 +86,8 @@
|
||||
"overrides": {
|
||||
"@types/bun": "catalog:",
|
||||
"@types/node": "catalog:"
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.0.110",
|
||||
"version": "1.0.137",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsgo --noEmit",
|
||||
@@ -18,6 +18,7 @@
|
||||
"@opencode-ai/console-core": "workspace:*",
|
||||
"@opencode-ai/console-mail": "workspace:*",
|
||||
"@opencode-ai/console-resource": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@solidjs/meta": "catalog:",
|
||||
"@solidjs/router": "catalog:",
|
||||
"@solidjs/start": "catalog:",
|
||||
|
||||
1
packages/console/app/public/apple-touch-icon.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/apple-touch-icon.png
|
||||
1
packages/console/app/public/favicon-96x96.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/favicon-96x96.png
|
||||
@@ -1,23 +0,0 @@
|
||||
<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="400" height="400" fill="#FDFCFC"/>
|
||||
<path d="M96 122.001V70.001H148V122.001H96Z" fill="#17181C"/>
|
||||
<path d="M148.004 122.001V70.001H200.004V122.001H148.004Z" fill="#17181C"/>
|
||||
<path d="M200.008 122.001V70.001H252.008V122.001H200.008Z" fill="#17181C"/>
|
||||
<path d="M251.996 122.001V70.001H303.996V122.001H251.996Z" fill="#17181C"/>
|
||||
<path d="M251.996 173.988V121.988H303.996V173.988H251.996Z" fill="#17181C"/>
|
||||
<path d="M96 225.998V173.998H148V225.998H96Z" fill="#CFCECD"/>
|
||||
<rect width="52" height="52" transform="translate(148.004 173.998)" fill="#17181C"/>
|
||||
<path d="M148.004 225.998V173.998H200.004V225.998H148.004Z" fill="#17181C" fill-opacity="0.1"/>
|
||||
<path d="M200.008 225.998V173.998H252.008V225.998H200.008Z" fill="#17181C"/>
|
||||
<path d="M252.016 225.998V173.998H304.016V225.998H252.016Z" fill="#CFCECD"/>
|
||||
<rect width="52" height="52" transform="translate(96 226.002)" fill="#17181C"/>
|
||||
<path d="M96 278.002V226.002H148V278.002H96Z" fill="#17181C" fill-opacity="0.1"/>
|
||||
<rect width="52" height="52" transform="translate(148.004 226.002)" fill="white"/>
|
||||
<path d="M148.004 278.002V226.002H200.004V278.002H148.004Z" fill="#CFCECD"/>
|
||||
<path d="M200.008 278.002V226.002H252.008V278.002H200.008Z" fill="#CFCECD"/>
|
||||
<path d="M252.016 278.002V226.002H304.016V278.002H252.016Z" fill="#CFCECD"/>
|
||||
<path d="M96 330.012V278.012H148V330.012H96Z" fill="#17181C"/>
|
||||
<path d="M148.004 330.012V278.012H200.004V330.012H148.004Z" fill="#17181C"/>
|
||||
<path d="M200.008 329.99V277.99H252.008V329.99H200.008Z" fill="#17181C"/>
|
||||
<path d="M251.996 330.012V278.012H303.996V330.012H251.996Z" fill="#17181C"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
1
packages/console/app/public/favicon.ico
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/favicon.ico
|
||||
@@ -2,4 +2,5 @@ User-agent: *
|
||||
Allow: /
|
||||
|
||||
# Disallow shared content pages
|
||||
Disallow: /s/
|
||||
Disallow: /s/
|
||||
Disallow: /share/
|
||||
1
packages/console/app/public/site.webmanifest
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/site.webmanifest
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 50 B |
1
packages/console/app/public/social-share-zen.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/images/social-share-zen.png
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 50 B |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 46 B |
1
packages/console/app/public/social-share.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/images/social-share.png
|
||||
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 46 B |
1
packages/console/app/public/web-app-manifest-192x192.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/web-app-manifest-192x192.png
|
||||
1
packages/console/app/public/web-app-manifest-512x512.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../ui/src/assets/favicon/web-app-manifest-512x512.png
|
||||
@@ -1,7 +1,8 @@
|
||||
import { MetaProvider, Title, Meta } from "@solidjs/meta"
|
||||
import { Router } from "@solidjs/router"
|
||||
import { FileRoutes } from "@solidjs/start/router"
|
||||
import { ErrorBoundary, Suspense } from "solid-js"
|
||||
import { Suspense } from "solid-js"
|
||||
import { Favicon } from "@opencode-ai/ui/favicon"
|
||||
import "@ibm/plex/css/ibm-plex.css"
|
||||
import "./app.css"
|
||||
|
||||
@@ -13,6 +14,7 @@ export default function App() {
|
||||
<MetaProvider>
|
||||
<Title>opencode</Title>
|
||||
<Meta name="description" content="OpenCode - The AI coding agent built for the terminal." />
|
||||
<Favicon />
|
||||
<Suspense>{props.children}</Suspense>
|
||||
</MetaProvider>
|
||||
)}
|
||||
|
||||
@@ -9,8 +9,8 @@ export const config = {
|
||||
github: {
|
||||
repoUrl: "https://github.com/sst/opencode",
|
||||
starsFormatted: {
|
||||
compact: "30K",
|
||||
full: "30,000",
|
||||
compact: "35K",
|
||||
full: "35,000",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -22,8 +22,8 @@ export const config = {
|
||||
|
||||
// Static stats (used on landing page)
|
||||
stats: {
|
||||
contributors: "300",
|
||||
commits: "4,000",
|
||||
monthlyUsers: "300,000",
|
||||
contributors: "350",
|
||||
commits: "5,000",
|
||||
monthlyUsers: "400,000",
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -9,7 +9,6 @@ export default createHandler(
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="shortcut icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta property="og:image" content="/social-share.png" />
|
||||
<meta property="twitter:image" content="/social-share.png" />
|
||||
{assets}
|
||||
|
||||
@@ -36,6 +36,7 @@ ${body.email}`.trim()
|
||||
to: "contact@anoma.ly",
|
||||
subject: `Enterprise Inquiry from ${body.name}`,
|
||||
body: emailContent,
|
||||
replyTo: body.email,
|
||||
})
|
||||
|
||||
return Response.json({ success: true, message: "Form submitted successfully" }, { status: 200 })
|
||||
|
||||
@@ -338,6 +338,11 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="installation-instructions"] {
|
||||
color: var(--color-text-strong);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
[data-slot="installation"] {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
@@ -348,6 +353,11 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="installation-options"] {
|
||||
font-size: 13px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
[data-component="tabs"] {
|
||||
[data-slot="tablist"] {
|
||||
display: flex;
|
||||
@@ -480,10 +490,10 @@ body {
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
font-size: 38px;
|
||||
color: var(--color-text-strong);
|
||||
font-weight: 500;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
@media (max-width: 60rem) {
|
||||
font-size: 22px;
|
||||
@@ -492,7 +502,7 @@ body {
|
||||
|
||||
p {
|
||||
color: var(--color-text);
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 40px;
|
||||
max-width: 82%;
|
||||
|
||||
@media (max-width: 50rem) {
|
||||
@@ -607,6 +617,25 @@ body {
|
||||
padding: var(--vertical-padding) var(--padding);
|
||||
color: var(--color-text);
|
||||
|
||||
a {
|
||||
background: var(--color-background-strong);
|
||||
padding: 8px 12px 8px 20px;
|
||||
color: var(--color-text-inverted);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
margin-top: 40px;
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
gap: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: var(--color-background-strong-hover);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
li {
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function Home() {
|
||||
return (
|
||||
<main data-page="opencode">
|
||||
{/*<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />*/}
|
||||
<Title>OpenCode | The AI coding agent built for the terminal</Title>
|
||||
<Title>OpenCode | The open source AI coding agent</Title>
|
||||
<Link rel="canonical" href={config.baseUrl} />
|
||||
<Meta property="og:image" content="/social-share.png" />
|
||||
<Meta name="twitter:image" content="/social-share.png" />
|
||||
@@ -56,23 +56,13 @@ export default function Home() {
|
||||
<a data-slot="releases" href={release()?.url ?? `${config.github.repoUrl}/releases`} target="_blank">
|
||||
What’s new in {release()?.name ?? "the latest release"}
|
||||
</a>
|
||||
<h1>The AI coding agent built for the terminal</h1>
|
||||
<h1>The open source coding agent</h1>
|
||||
<p>
|
||||
OpenCode is fully open source, giving you control and freedom to use any provider, any model, and any
|
||||
editor.
|
||||
OpenCode includes free models or connect from any provider to <br />
|
||||
use other models, including Claude, GPT, Gemini and more.
|
||||
</p>
|
||||
<a href="/docs">
|
||||
<span>Read docs </span>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="square"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<p data-slot="installation-instructions">Install and use. No account, no email, and no credit card.</p>
|
||||
<div data-slot="installation">
|
||||
<Tabs
|
||||
as="section"
|
||||
@@ -151,6 +141,11 @@ export default function Home() {
|
||||
</div>
|
||||
</Tabs>
|
||||
</div>
|
||||
<p data-slot="installation-options">
|
||||
Available in terminal, web, and desktop (coming soon).
|
||||
<br />
|
||||
Extensions for VS Code, Cursor, Windsurf, and more.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-component="video">
|
||||
@@ -208,6 +203,17 @@ export default function Home() {
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="/docs">
|
||||
<span>Read docs </span>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="square"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section data-component="growth">
|
||||
|
||||
7
packages/console/app/src/routes/openapi.json.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export async function GET() {
|
||||
const response = await fetch(
|
||||
"https://raw.githubusercontent.com/sst/opencode/refs/heads/dev/packages/sdk/openapi.json",
|
||||
)
|
||||
const json = await response.json()
|
||||
return json
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import "./workspace-picker.css"
|
||||
const getWorkspaces = query(async () => {
|
||||
"use server"
|
||||
return withActor(async () => {
|
||||
return Database.transaction((tx) =>
|
||||
return Database.use((tx) =>
|
||||
tx
|
||||
.select({
|
||||
id: WorkspaceTable.id,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { UserMenu } from "./user-menu"
|
||||
import { withActor } from "~/context/auth.withActor"
|
||||
import { User } from "@opencode-ai/console-core/user.js"
|
||||
import { Actor } from "@opencode-ai/console-core/actor.js"
|
||||
import { Link } from "@solidjs/meta"
|
||||
|
||||
const getUserEmail = query(async (workspaceID: string) => {
|
||||
"use server"
|
||||
@@ -22,7 +21,6 @@ export default function WorkspaceLayout(props: RouteSectionProps) {
|
||||
const userEmail = createAsync(() => getUserEmail(params.id!))
|
||||
return (
|
||||
<main data-page="workspace">
|
||||
<Link rel="shortcut icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
||||
<header data-component="workspace-header">
|
||||
<div data-slot="header-brand">
|
||||
<A href="/" data-component="site-title">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { UsageTable } from "@opencode-ai/console-core/schema/billing.sql.js"
|
||||
import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
|
||||
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
|
||||
import { AuthTable } from "@opencode-ai/console-core/schema/auth.sql.js"
|
||||
import { createAsync, query, useParams } from "@solidjs/router"
|
||||
import { useParams } from "@solidjs/router"
|
||||
import { createEffect, createMemo, onCleanup, Show, For } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { withActor } from "~/context/auth.withActor"
|
||||
@@ -94,8 +94,6 @@ async function getCosts(workspaceID: string, year: number, month: number) {
|
||||
}, workspaceID)
|
||||
}
|
||||
|
||||
const queryCosts = query(getCosts, "costs.get")
|
||||
|
||||
const MODEL_COLORS: Record<string, string> = {
|
||||
"claude-sonnet-4-5": "#D4745C",
|
||||
"claude-sonnet-4": "#E8B4A4",
|
||||
@@ -158,32 +156,27 @@ export function GraphSection() {
|
||||
model: null as string | null,
|
||||
modelDropdownOpen: false,
|
||||
keyDropdownOpen: false,
|
||||
colorScheme: "light" as "light" | "dark",
|
||||
})
|
||||
const initialData = createAsync(() => queryCosts(params.id!, store.year, store.month))
|
||||
|
||||
const onPreviousMonth = async () => {
|
||||
const month = store.month === 0 ? 11 : store.month - 1
|
||||
const year = store.month === 0 ? store.year - 1 : store.year
|
||||
const data = await getCosts(params.id!, year, month)
|
||||
setStore({ month, year, data })
|
||||
setStore({ month, year })
|
||||
}
|
||||
|
||||
const onNextMonth = async () => {
|
||||
const month = store.month === 11 ? 0 : store.month + 1
|
||||
const year = store.month === 11 ? store.year + 1 : store.year
|
||||
setStore({ month, year, data: await getCosts(params.id!, year, month) })
|
||||
setStore({ month, year })
|
||||
}
|
||||
|
||||
const onSelectModel = (model: string | null) => setStore({ model, modelDropdownOpen: false })
|
||||
|
||||
const onSelectKey = (keyID: string | null) => setStore({ key: keyID, keyDropdownOpen: false })
|
||||
|
||||
const getData = createMemo(() => store.data ?? initialData())
|
||||
|
||||
const getModels = createMemo(() => {
|
||||
const data = getData()
|
||||
if (!data?.usage) return []
|
||||
return Array.from(new Set(data.usage.map((row) => row.model))).sort()
|
||||
if (!store.data?.usage) return []
|
||||
return Array.from(new Set(store.data.usage.map((row) => row.model))).sort()
|
||||
})
|
||||
|
||||
const getDates = createMemo(() => {
|
||||
@@ -206,10 +199,19 @@ export function GraphSection() {
|
||||
const isCurrentMonth = () => store.year === now.getFullYear() && store.month === now.getMonth()
|
||||
|
||||
const chartConfig = createMemo((): ChartConfiguration | null => {
|
||||
const data = getData()
|
||||
const data = store.data
|
||||
const dates = getDates()
|
||||
if (!data?.usage?.length) return null
|
||||
|
||||
store.colorScheme
|
||||
const styles = getComputedStyle(document.documentElement)
|
||||
const colorTextMuted = styles.getPropertyValue("--color-text-muted").trim()
|
||||
const colorBorderMuted = styles.getPropertyValue("--color-border-muted").trim()
|
||||
const colorBgElevated = styles.getPropertyValue("--color-bg-elevated").trim()
|
||||
const colorText = styles.getPropertyValue("--color-text").trim()
|
||||
const colorTextSecondary = styles.getPropertyValue("--color-text-secondary").trim()
|
||||
const colorBorder = styles.getPropertyValue("--color-border").trim()
|
||||
|
||||
const dailyData = new Map<string, Map<string, number>>()
|
||||
for (const dateKey of dates) dailyData.set(dateKey, new Map())
|
||||
|
||||
@@ -252,7 +254,7 @@ export function GraphSection() {
|
||||
ticks: {
|
||||
maxRotation: 0,
|
||||
autoSkipPadding: 20,
|
||||
color: "rgba(255, 255, 255, 0.5)",
|
||||
color: colorTextMuted,
|
||||
font: {
|
||||
family: "monospace",
|
||||
size: 11,
|
||||
@@ -263,10 +265,10 @@ export function GraphSection() {
|
||||
stacked: true,
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
color: "rgba(255, 255, 255, 0.1)",
|
||||
color: colorBorderMuted,
|
||||
},
|
||||
ticks: {
|
||||
color: "rgba(255, 255, 255, 0.5)",
|
||||
color: colorTextMuted,
|
||||
font: {
|
||||
family: "monospace",
|
||||
size: 11,
|
||||
@@ -282,10 +284,10 @@ export function GraphSection() {
|
||||
tooltip: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.9)",
|
||||
titleColor: "rgba(255, 255, 255, 0.9)",
|
||||
bodyColor: "rgba(255, 255, 255, 0.8)",
|
||||
borderColor: "rgba(255, 255, 255, 0.1)",
|
||||
backgroundColor: colorBgElevated,
|
||||
titleColor: colorText,
|
||||
bodyColor: colorTextSecondary,
|
||||
borderColor: colorBorder,
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
displayColors: true,
|
||||
@@ -301,7 +303,7 @@ export function GraphSection() {
|
||||
display: true,
|
||||
position: "bottom",
|
||||
labels: {
|
||||
color: "rgba(255, 255, 255, 0.7)",
|
||||
color: colorTextSecondary,
|
||||
font: {
|
||||
size: 12,
|
||||
},
|
||||
@@ -339,15 +341,32 @@ export function GraphSection() {
|
||||
}
|
||||
})
|
||||
|
||||
createEffect(async () => {
|
||||
const data = await getCosts(params.id!, store.year, store.month)
|
||||
setStore({ data })
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const config = chartConfig()
|
||||
if (!config || !canvasRef) return
|
||||
|
||||
if (chartInstance) chartInstance.destroy()
|
||||
chartInstance = new Chart(canvasRef, config)
|
||||
|
||||
onCleanup(() => chartInstance?.destroy())
|
||||
})
|
||||
|
||||
onCleanup(() => chartInstance?.destroy())
|
||||
createEffect(() => {
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
|
||||
setStore({ colorScheme: mediaQuery.matches ? "dark" : "light" })
|
||||
|
||||
const handleColorSchemeChange = (e: MediaQueryListEvent) => {
|
||||
setStore({ colorScheme: e.matches ? "dark" : "light" })
|
||||
}
|
||||
|
||||
mediaQuery.addEventListener("change", handleColorSchemeChange)
|
||||
onCleanup(() => mediaQuery.removeEventListener("change", handleColorSchemeChange))
|
||||
})
|
||||
|
||||
return (
|
||||
<section class={styles.root}>
|
||||
@@ -356,55 +375,53 @@ export function GraphSection() {
|
||||
<p>Usage costs broken down by model.</p>
|
||||
</div>
|
||||
|
||||
<Show when={getData()}>
|
||||
<div data-slot="filter-container">
|
||||
<div data-slot="month-picker">
|
||||
<button data-slot="month-button" onClick={onPreviousMonth}>
|
||||
<IconChevronLeft />
|
||||
</button>
|
||||
<span data-slot="month-label">{formatMonthYear()}</span>
|
||||
<button data-slot="month-button" onClick={onNextMonth} disabled={isCurrentMonth()}>
|
||||
<IconChevronRight />
|
||||
</button>
|
||||
</div>
|
||||
<Dropdown
|
||||
trigger={store.model === null ? "All Models" : store.model}
|
||||
open={store.modelDropdownOpen}
|
||||
onOpenChange={(open) => setStore({ modelDropdownOpen: open })}
|
||||
>
|
||||
<>
|
||||
<button data-slot="model-item" onClick={() => onSelectModel(null)}>
|
||||
<span>All Models</span>
|
||||
</button>
|
||||
<For each={getModels()}>
|
||||
{(model) => (
|
||||
<button data-slot="model-item" onClick={() => onSelectModel(model)}>
|
||||
<span>{model}</span>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</>
|
||||
</Dropdown>
|
||||
<Dropdown
|
||||
trigger={getKeyName(store.key)}
|
||||
open={store.keyDropdownOpen}
|
||||
onOpenChange={(open) => setStore({ keyDropdownOpen: open })}
|
||||
>
|
||||
<>
|
||||
<button data-slot="model-item" onClick={() => onSelectKey(null)}>
|
||||
<span>All Keys</span>
|
||||
</button>
|
||||
<For each={getData()?.keys || []}>
|
||||
{(key) => (
|
||||
<button data-slot="model-item" onClick={() => onSelectKey(key.id)}>
|
||||
<span>{key.displayName}</span>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</>
|
||||
</Dropdown>
|
||||
<div data-slot="filter-container">
|
||||
<div data-slot="month-picker">
|
||||
<button data-slot="month-button" onClick={onPreviousMonth}>
|
||||
<IconChevronLeft />
|
||||
</button>
|
||||
<span data-slot="month-label">{formatMonthYear()}</span>
|
||||
<button data-slot="month-button" onClick={onNextMonth} disabled={isCurrentMonth()}>
|
||||
<IconChevronRight />
|
||||
</button>
|
||||
</div>
|
||||
</Show>
|
||||
<Dropdown
|
||||
trigger={store.model === null ? "All Models" : store.model}
|
||||
open={store.modelDropdownOpen}
|
||||
onOpenChange={(open) => setStore({ modelDropdownOpen: open })}
|
||||
>
|
||||
<>
|
||||
<button data-slot="model-item" onClick={() => onSelectModel(null)}>
|
||||
<span>All Models</span>
|
||||
</button>
|
||||
<For each={getModels()}>
|
||||
{(model) => (
|
||||
<button data-slot="model-item" onClick={() => onSelectModel(model)}>
|
||||
<span>{model}</span>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</>
|
||||
</Dropdown>
|
||||
<Dropdown
|
||||
trigger={getKeyName(store.key)}
|
||||
open={store.keyDropdownOpen}
|
||||
onOpenChange={(open) => setStore({ keyDropdownOpen: open })}
|
||||
>
|
||||
<>
|
||||
<button data-slot="model-item" onClick={() => onSelectKey(null)}>
|
||||
<span>All Keys</span>
|
||||
</button>
|
||||
<For each={store.data?.keys || []}>
|
||||
{(key) => (
|
||||
<button data-slot="model-item" onClick={() => onSelectKey(key.id)}>
|
||||
<span>{key.displayName}</span>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
<Show
|
||||
when={chartConfig()}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Legal } from "~/component/legal"
|
||||
import { Footer } from "~/component/footer"
|
||||
import { Header } from "~/component/header"
|
||||
import { getLastSeenWorkspaceID } from "../workspace/common"
|
||||
import { IconGemini } from "~/component/icon"
|
||||
import { IconGemini, IconZai } from "~/component/icon"
|
||||
|
||||
const checkLoggedIn = query(async () => {
|
||||
"use server"
|
||||
@@ -33,7 +33,6 @@ export default function Home() {
|
||||
{/*<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />*/}
|
||||
<Title>OpenCode Zen | A curated set of reliable optimized models for coding agents</Title>
|
||||
<Link rel="canonical" href={`${config.baseUrl}/zen`} />
|
||||
<Link rel="shortcut icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
||||
<Meta property="og:image" content="/social-share-zen.png" />
|
||||
<Meta name="twitter:image" content="/social-share-zen.png" />
|
||||
<Meta name="opencode:auth" content={loggedin() ? "true" : "false"} />
|
||||
@@ -116,6 +115,9 @@ export default function Home() {
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<IconZai width="24" height="24" />
|
||||
</div>
|
||||
</div>
|
||||
<a href="/auth">
|
||||
<span>Get started with Zen </span>
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
import { Resource, waitUntil } from "@opencode-ai/console-resource"
|
||||
|
||||
export function createDataDumper(sessionId: string, requestId: string) {
|
||||
export function createDataDumper(sessionId: string, requestId: string, projectId: string) {
|
||||
if (Resource.App.stage !== "production") return
|
||||
if (sessionId === "") return
|
||||
|
||||
let data: Record<string, any> = {}
|
||||
let modelName: string | undefined
|
||||
let data: Record<string, any> = { sessionId, requestId, projectId }
|
||||
let metadata: Record<string, any> = { sessionId, requestId, projectId }
|
||||
|
||||
return {
|
||||
provideModel: (model?: string) => (modelName = model),
|
||||
provideModel: (model?: string) => {
|
||||
data.modelName = model
|
||||
metadata.modelName = model
|
||||
},
|
||||
provideRequest: (request: string) => (data.request = request),
|
||||
provideResponse: (response: string) => (data.response = response),
|
||||
provideStream: (chunk: string) => (data.response = (data.response ?? "") + chunk),
|
||||
flush: () => {
|
||||
if (!modelName) return
|
||||
if (!data.modelName) return
|
||||
|
||||
const str = new Date().toISOString().replace(/[^0-9]/g, "")
|
||||
const yyyymmdd = str.substring(0, 8)
|
||||
const hh = str.substring(8, 10)
|
||||
const timestamp = new Date().toISOString().replace(/[^0-9]/g, "")
|
||||
|
||||
waitUntil(
|
||||
Resource.ConsoleData.put(`${yyyymmdd}/${hh}/${modelName}/${sessionId}/${requestId}.json`, JSON.stringify(data)),
|
||||
Resource.ZenData.put(
|
||||
`data/${data.modelName}/${sessionId}/${requestId}.json`,
|
||||
JSON.stringify({ timestamp, ...data }),
|
||||
),
|
||||
)
|
||||
|
||||
waitUntil(
|
||||
Resource.ZenData.put(
|
||||
`meta/${data.modelName}/${timestamp}/${requestId}.json`,
|
||||
JSON.stringify({ timestamp, ...metadata }),
|
||||
),
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -13,13 +13,15 @@ import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
|
||||
import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
|
||||
import { logger } from "./logger"
|
||||
import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError, RateLimitError } from "./error"
|
||||
import { createBodyConverter, createStreamPartConverter, createResponseConverter } from "./provider/provider"
|
||||
import { createBodyConverter, createStreamPartConverter, createResponseConverter, UsageInfo } from "./provider/provider"
|
||||
import { anthropicHelper } from "./provider/anthropic"
|
||||
import { googleHelper } from "./provider/google"
|
||||
import { openaiHelper } from "./provider/openai"
|
||||
import { oaCompatHelper } from "./provider/openai-compatible"
|
||||
import { createRateLimiter } from "./rateLimiter"
|
||||
import { createDataDumper } from "./dataDumper"
|
||||
import { createTrialLimiter } from "./trialLimiter"
|
||||
import { createStickyTracker } from "./stickyProviderTracker"
|
||||
|
||||
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
||||
type RetryOptions = {
|
||||
@@ -54,6 +56,7 @@ export async function handler(
|
||||
const ip = input.request.headers.get("x-real-ip") ?? ""
|
||||
const sessionId = input.request.headers.get("x-opencode-session") ?? ""
|
||||
const requestId = input.request.headers.get("x-opencode-request") ?? ""
|
||||
const projectId = input.request.headers.get("x-opencode-project") ?? ""
|
||||
logger.metric({
|
||||
is_tream: isStream,
|
||||
session: sessionId,
|
||||
@@ -61,13 +64,25 @@ export async function handler(
|
||||
})
|
||||
const zenData = ZenData.list()
|
||||
const modelInfo = validateModel(zenData, model)
|
||||
const dataDumper = createDataDumper(sessionId, requestId)
|
||||
const dataDumper = createDataDumper(sessionId, requestId, projectId)
|
||||
const trialLimiter = createTrialLimiter(modelInfo.trial?.limit, ip)
|
||||
const isTrial = await trialLimiter?.isTrial()
|
||||
const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip)
|
||||
await rateLimiter?.check()
|
||||
const stickyTracker = createStickyTracker(modelInfo.stickyProvider ?? false, sessionId)
|
||||
const stickyProvider = await stickyTracker?.get()
|
||||
|
||||
const retriableRequest = async (retry: RetryOptions = { excludeProviders: [], retryCount: 0 }) => {
|
||||
const providerInfo = selectProvider(zenData, modelInfo, ip, retry)
|
||||
const authInfo = await authenticate(modelInfo, providerInfo)
|
||||
const authInfo = await authenticate(modelInfo)
|
||||
const providerInfo = selectProvider(
|
||||
zenData,
|
||||
authInfo,
|
||||
modelInfo,
|
||||
sessionId,
|
||||
isTrial ?? false,
|
||||
retry,
|
||||
stickyProvider,
|
||||
)
|
||||
validateBilling(authInfo, modelInfo)
|
||||
validateModelSettings(authInfo)
|
||||
updateProviderKey(authInfo, providerInfo)
|
||||
@@ -117,6 +132,9 @@ export async function handler(
|
||||
dataDumper?.provideModel(providerInfo.storeModel)
|
||||
dataDumper?.provideRequest(reqBody)
|
||||
|
||||
// Store sticky provider
|
||||
await stickyTracker?.set(providerInfo.id)
|
||||
|
||||
// Scrub response headers
|
||||
const resHeaders = new Headers()
|
||||
const keepHeaders = ["content-type", "cache-control"]
|
||||
@@ -136,8 +154,10 @@ export async function handler(
|
||||
logger.debug("RESPONSE: " + body)
|
||||
dataDumper?.provideResponse(body)
|
||||
dataDumper?.flush()
|
||||
const tokensInfo = providerInfo.normalizeUsage(json.usage)
|
||||
await trialLimiter?.track(tokensInfo)
|
||||
await rateLimiter?.track()
|
||||
await trackUsage(authInfo, modelInfo, providerInfo, json.usage)
|
||||
await trackUsage(authInfo, modelInfo, providerInfo, tokensInfo)
|
||||
await reload(authInfo)
|
||||
return new Response(body, {
|
||||
status: res.status,
|
||||
@@ -169,7 +189,9 @@ export async function handler(
|
||||
await rateLimiter?.track()
|
||||
const usage = usageParser.retrieve()
|
||||
if (usage) {
|
||||
await trackUsage(authInfo, modelInfo, providerInfo, usage)
|
||||
const tokensInfo = providerInfo.normalizeUsage(usage)
|
||||
await trialLimiter?.track(tokensInfo)
|
||||
await trackUsage(authInfo, modelInfo, providerInfo, tokensInfo)
|
||||
await reload(authInfo)
|
||||
}
|
||||
c.close()
|
||||
@@ -275,8 +297,29 @@ export async function handler(
|
||||
return { id: modelId, ...modelData }
|
||||
}
|
||||
|
||||
function selectProvider(zenData: ZenData, modelInfo: ModelInfo, ip: string, retry: RetryOptions) {
|
||||
function selectProvider(
|
||||
zenData: ZenData,
|
||||
authInfo: AuthInfo,
|
||||
modelInfo: ModelInfo,
|
||||
sessionId: string,
|
||||
isTrial: boolean,
|
||||
retry: RetryOptions,
|
||||
stickyProvider: string | undefined,
|
||||
) {
|
||||
const provider = (() => {
|
||||
if (authInfo?.provider?.credentials) {
|
||||
return modelInfo.providers.find((provider) => provider.id === modelInfo.byokProvider)
|
||||
}
|
||||
|
||||
if (isTrial) {
|
||||
return modelInfo.providers.find((provider) => provider.id === modelInfo.trial!.provider)
|
||||
}
|
||||
|
||||
if (stickyProvider) {
|
||||
const provider = modelInfo.providers.find((provider) => provider.id === stickyProvider)
|
||||
if (provider) return provider
|
||||
}
|
||||
|
||||
if (retry.retryCount === MAX_RETRIES) {
|
||||
return modelInfo.providers.find((provider) => provider.id === modelInfo.fallbackProvider)
|
||||
}
|
||||
@@ -286,9 +329,13 @@ export async function handler(
|
||||
.filter((provider) => !retry.excludeProviders.includes(provider.id))
|
||||
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
|
||||
|
||||
// Use the last 2 characters of IP address to select a provider
|
||||
const lastChars = ip.slice(-2)
|
||||
const index = parseInt(lastChars, 16) % providers.length
|
||||
// Use the last 4 characters of session ID to select a provider
|
||||
let h = 0
|
||||
const l = sessionId.length
|
||||
for (let i = l - 4; i < l; i++) {
|
||||
h = (h * 31 + sessionId.charCodeAt(i)) | 0 // 32-bit int
|
||||
}
|
||||
const index = (h >>> 0) % providers.length // make unsigned + range 0..length-1
|
||||
return providers[index || 0]
|
||||
})()
|
||||
|
||||
@@ -308,7 +355,7 @@ export async function handler(
|
||||
}
|
||||
}
|
||||
|
||||
async function authenticate(modelInfo: ModelInfo, providerInfo: ProviderInfo) {
|
||||
async function authenticate(modelInfo: ModelInfo) {
|
||||
const apiKey = opts.parseApiKey(input.request.headers)
|
||||
if (!apiKey || apiKey === "public") {
|
||||
if (modelInfo.allowAnonymous) return
|
||||
@@ -346,7 +393,12 @@ export async function handler(
|
||||
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, modelInfo.id)))
|
||||
.leftJoin(
|
||||
ProviderTable,
|
||||
and(eq(ProviderTable.workspaceID, KeyTable.workspaceID), eq(ProviderTable.provider, providerInfo.id)),
|
||||
modelInfo.byokProvider
|
||||
? and(
|
||||
eq(ProviderTable.workspaceID, KeyTable.workspaceID),
|
||||
eq(ProviderTable.provider, modelInfo.byokProvider),
|
||||
)
|
||||
: sql`false`,
|
||||
)
|
||||
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
||||
.then((rows) => rows[0]),
|
||||
@@ -423,14 +475,18 @@ export async function handler(
|
||||
}
|
||||
|
||||
function updateProviderKey(authInfo: AuthInfo, providerInfo: ProviderInfo) {
|
||||
if (!authInfo) return
|
||||
if (!authInfo.provider?.credentials) return
|
||||
if (!authInfo?.provider?.credentials) return
|
||||
providerInfo.apiKey = authInfo.provider.credentials
|
||||
}
|
||||
|
||||
async function trackUsage(authInfo: AuthInfo, modelInfo: ModelInfo, providerInfo: ProviderInfo, usage: any) {
|
||||
async function trackUsage(
|
||||
authInfo: AuthInfo,
|
||||
modelInfo: ModelInfo,
|
||||
providerInfo: ProviderInfo,
|
||||
usageInfo: UsageInfo,
|
||||
) {
|
||||
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
|
||||
providerInfo.normalizeUsage(usage)
|
||||
usageInfo
|
||||
|
||||
const modelCost =
|
||||
modelInfo.cost200K &&
|
||||
|
||||
@@ -24,6 +24,15 @@ import {
|
||||
toOaCompatibleResponse,
|
||||
} from "./openai-compatible"
|
||||
|
||||
export type UsageInfo = {
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
reasoningTokens?: number
|
||||
cacheReadTokens?: number
|
||||
cacheWrite5mTokens?: number
|
||||
cacheWrite1hTokens?: number
|
||||
}
|
||||
|
||||
export type ProviderHelper = {
|
||||
format: ZenData.Format
|
||||
modifyUrl: (providerApi: string, model?: string, isStream?: boolean) => string
|
||||
@@ -34,14 +43,7 @@ export type ProviderHelper = {
|
||||
parse: (chunk: string) => void
|
||||
retrieve: () => any
|
||||
}
|
||||
normalizeUsage: (usage: any) => {
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
reasoningTokens?: number
|
||||
cacheReadTokens?: number
|
||||
cacheWrite5mTokens?: number
|
||||
cacheWrite1hTokens?: number
|
||||
}
|
||||
normalizeUsage: (usage: any) => UsageInfo
|
||||
}
|
||||
|
||||
export interface CommonMessage {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Resource } from "@opencode-ai/console-resource"
|
||||
|
||||
export function createStickyTracker(stickyProvider: boolean, session: string) {
|
||||
if (!stickyProvider) return
|
||||
if (!session) return
|
||||
const key = `sticky:${session}`
|
||||
|
||||
return {
|
||||
get: async () => {
|
||||
return await Resource.GatewayKv.get(key)
|
||||
},
|
||||
set: async (providerId: string) => {
|
||||
await Resource.GatewayKv.put(key, providerId, { expirationTtl: 86400 })
|
||||
},
|
||||
}
|
||||
}
|
||||
43
packages/console/app/src/routes/zen/util/trialLimiter.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Database, eq, sql } from "@opencode-ai/console-core/drizzle/index.js"
|
||||
import { IpTable } from "@opencode-ai/console-core/schema/ip.sql.js"
|
||||
import { UsageInfo } from "./provider/provider"
|
||||
|
||||
export function createTrialLimiter(limit: number | undefined, ip: string) {
|
||||
if (!limit) return
|
||||
if (!ip) return
|
||||
|
||||
let trial: boolean
|
||||
|
||||
return {
|
||||
isTrial: async () => {
|
||||
const data = await Database.use((tx) =>
|
||||
tx
|
||||
.select({
|
||||
usage: IpTable.usage,
|
||||
})
|
||||
.from(IpTable)
|
||||
.where(eq(IpTable.ip, ip))
|
||||
.then((rows) => rows[0]),
|
||||
)
|
||||
|
||||
trial = (data?.usage ?? 0) < limit
|
||||
return trial
|
||||
},
|
||||
track: async (usageInfo: UsageInfo) => {
|
||||
if (!trial) return
|
||||
const usage =
|
||||
usageInfo.inputTokens +
|
||||
usageInfo.outputTokens +
|
||||
(usageInfo.reasoningTokens ?? 0) +
|
||||
(usageInfo.cacheReadTokens ?? 0) +
|
||||
(usageInfo.cacheWrite5mTokens ?? 0) +
|
||||
(usageInfo.cacheWrite1hTokens ?? 0)
|
||||
await Database.use((tx) =>
|
||||
tx
|
||||
.insert(IpTable)
|
||||
.values({ ip, usage })
|
||||
.onDuplicateKeyUpdate({ set: { usage: sql`${IpTable.usage} + ${usage}` } }),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
2
packages/console/app/sst-env.d.ts
vendored
@@ -6,4 +6,4 @@
|
||||
/// <reference path="../../../sst-env.d.ts" />
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
8
packages/console/core/migrations/0038_famous_magik.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
CREATE TABLE `ip` (
|
||||
`ip` varchar(45) NOT NULL,
|
||||
`time_created` timestamp(3) NOT NULL DEFAULT (now()),
|
||||
`time_updated` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
`time_deleted` timestamp(3),
|
||||
`usage` int,
|
||||
CONSTRAINT `ip_ip_pk` PRIMARY KEY(`ip`)
|
||||
);
|
||||
981
packages/console/core/migrations/meta/0038_snapshot.json
Normal file
@@ -0,0 +1,981 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "mysql",
|
||||
"id": "9d5d9885-7ec5-45f6-ac53-45a8e25dede7",
|
||||
"prevId": "8b7fa839-a088-408e-84a4-1a07325c0290",
|
||||
"tables": {
|
||||
"account": {
|
||||
"name": "account",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"account_id_pk": {
|
||||
"name": "account_id_pk",
|
||||
"columns": ["id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"auth": {
|
||||
"name": "auth",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"type": "enum('email','github','google')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"subject": {
|
||||
"name": "subject",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"account_id": {
|
||||
"name": "account_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"columns": ["provider", "subject"],
|
||||
"isUnique": true
|
||||
},
|
||||
"account_id": {
|
||||
"name": "account_id",
|
||||
"columns": ["account_id"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"auth_id_pk": {
|
||||
"name": "auth_id_pk",
|
||||
"columns": ["id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"billing": {
|
||||
"name": "billing",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"customer_id": {
|
||||
"name": "customer_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"payment_method_id": {
|
||||
"name": "payment_method_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"payment_method_type": {
|
||||
"name": "payment_method_type",
|
||||
"type": "varchar(32)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"payment_method_last4": {
|
||||
"name": "payment_method_last4",
|
||||
"type": "varchar(4)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"balance": {
|
||||
"name": "balance",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"monthly_limit": {
|
||||
"name": "monthly_limit",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"monthly_usage": {
|
||||
"name": "monthly_usage",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_monthly_usage_updated": {
|
||||
"name": "time_monthly_usage_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"reload": {
|
||||
"name": "reload",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"reload_trigger": {
|
||||
"name": "reload_trigger",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"reload_amount": {
|
||||
"name": "reload_amount",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"reload_error": {
|
||||
"name": "reload_error",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_reload_error": {
|
||||
"name": "time_reload_error",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_reload_locked_till": {
|
||||
"name": "time_reload_locked_till",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"global_customer_id": {
|
||||
"name": "global_customer_id",
|
||||
"columns": ["customer_id"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"billing_workspace_id_id_pk": {
|
||||
"name": "billing_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"payment": {
|
||||
"name": "payment",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"customer_id": {
|
||||
"name": "customer_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"invoice_id": {
|
||||
"name": "invoice_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"payment_id": {
|
||||
"name": "payment_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"amount": {
|
||||
"name": "amount",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_refunded": {
|
||||
"name": "time_refunded",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"payment_workspace_id_id_pk": {
|
||||
"name": "payment_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"usage": {
|
||||
"name": "usage",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"model": {
|
||||
"name": "model",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"input_tokens": {
|
||||
"name": "input_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"output_tokens": {
|
||||
"name": "output_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"reasoning_tokens": {
|
||||
"name": "reasoning_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"cache_read_tokens": {
|
||||
"name": "cache_read_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"cache_write_5m_tokens": {
|
||||
"name": "cache_write_5m_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"cache_write_1h_tokens": {
|
||||
"name": "cache_write_1h_tokens",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"cost": {
|
||||
"name": "cost",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"key_id": {
|
||||
"name": "key_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"usage_workspace_id_id_pk": {
|
||||
"name": "usage_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"ip": {
|
||||
"name": "ip",
|
||||
"columns": {
|
||||
"ip": {
|
||||
"name": "ip",
|
||||
"type": "varchar(45)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"usage": {
|
||||
"name": "usage",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"ip_ip_pk": {
|
||||
"name": "ip_ip_pk",
|
||||
"columns": ["ip"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"key": {
|
||||
"name": "key",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"key": {
|
||||
"name": "key",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_used": {
|
||||
"name": "time_used",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"global_key": {
|
||||
"name": "global_key",
|
||||
"columns": ["key"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"key_workspace_id_id_pk": {
|
||||
"name": "key_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"model": {
|
||||
"name": "model",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"model": {
|
||||
"name": "model",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"model_workspace_model": {
|
||||
"name": "model_workspace_model",
|
||||
"columns": ["workspace_id", "model"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"model_workspace_id_id_pk": {
|
||||
"name": "model_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"type": "varchar(64)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"credentials": {
|
||||
"name": "credentials",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"workspace_provider": {
|
||||
"name": "workspace_provider",
|
||||
"columns": ["workspace_id", "provider"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"provider_workspace_id_id_pk": {
|
||||
"name": "provider_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"user": {
|
||||
"name": "user",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"account_id": {
|
||||
"name": "account_id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_seen": {
|
||||
"name": "time_seen",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"color": {
|
||||
"name": "color",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "enum('admin','member')",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"monthly_limit": {
|
||||
"name": "monthly_limit",
|
||||
"type": "int",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"monthly_usage": {
|
||||
"name": "monthly_usage",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_monthly_usage_updated": {
|
||||
"name": "time_monthly_usage_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_account_id": {
|
||||
"name": "user_account_id",
|
||||
"columns": ["workspace_id", "account_id"],
|
||||
"isUnique": true
|
||||
},
|
||||
"user_email": {
|
||||
"name": "user_email",
|
||||
"columns": ["workspace_id", "email"],
|
||||
"isUnique": true
|
||||
},
|
||||
"global_account_id": {
|
||||
"name": "global_account_id",
|
||||
"columns": ["account_id"],
|
||||
"isUnique": false
|
||||
},
|
||||
"global_email": {
|
||||
"name": "global_email",
|
||||
"columns": ["email"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"user_workspace_id_id_pk": {
|
||||
"name": "user_workspace_id_id_pk",
|
||||
"columns": ["workspace_id", "id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
},
|
||||
"workspace": {
|
||||
"name": "workspace",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "varchar(30)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"time_created": {
|
||||
"name": "time_created",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(now())"
|
||||
},
|
||||
"time_updated": {
|
||||
"name": "time_updated",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
|
||||
},
|
||||
"time_deleted": {
|
||||
"name": "time_deleted",
|
||||
"type": "timestamp(3)",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"columns": ["slug"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"workspace_id": {
|
||||
"name": "workspace_id",
|
||||
"columns": ["id"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraint": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"tables": {},
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
@@ -267,6 +267,13 @@
|
||||
"when": 1761928273807,
|
||||
"tag": "0037_messy_jackal",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 38,
|
||||
"version": "5",
|
||||
"when": 1764110043942,
|
||||
"tag": "0038_famous_magik",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.0.110",
|
||||
"version": "1.0.137",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
@@ -11,7 +11,7 @@ export namespace Account {
|
||||
id: z.string().optional(),
|
||||
}),
|
||||
async (input) =>
|
||||
Database.transaction(async (tx) => {
|
||||
Database.use(async (tx) => {
|
||||
const id = input.id ?? Identifier.create("account")
|
||||
await tx.insert(AccountTable).values({
|
||||
id,
|
||||
@@ -21,13 +21,12 @@ export namespace Account {
|
||||
)
|
||||
|
||||
export const fromID = fn(z.string(), async (id) =>
|
||||
Database.transaction(async (tx) => {
|
||||
return tx
|
||||
Database.use((tx) =>
|
||||
tx
|
||||
.select()
|
||||
.from(AccountTable)
|
||||
.where(eq(AccountTable.id, id))
|
||||
.execute()
|
||||
.then((rows) => rows[0])
|
||||
}),
|
||||
.then((rows) => rows[0]),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ export namespace AWS {
|
||||
to: z.string(),
|
||||
subject: z.string(),
|
||||
body: z.string(),
|
||||
replyTo: z.string().optional(),
|
||||
}),
|
||||
async (input) => {
|
||||
const res = await createClient().fetch("https://email.us-east-1.amazonaws.com/v2/email/outbound-emails", {
|
||||
@@ -35,6 +36,7 @@ export namespace AWS {
|
||||
Destination: {
|
||||
ToAddresses: [input.to],
|
||||
},
|
||||
...(input.replyTo && { ReplyToAddresses: [input.replyTo] }),
|
||||
Content: {
|
||||
Simple: {
|
||||
Subject: {
|
||||
|
||||
@@ -24,6 +24,14 @@ export namespace ZenData {
|
||||
cost: ModelCostSchema,
|
||||
cost200K: ModelCostSchema.optional(),
|
||||
allowAnonymous: z.boolean().optional(),
|
||||
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
|
||||
stickyProvider: z.boolean().optional(),
|
||||
trial: z
|
||||
.object({
|
||||
limit: z.number(),
|
||||
provider: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
rateLimit: z.number().optional(),
|
||||
fallbackProvider: z.string().optional(),
|
||||
providers: z.array(
|
||||
|
||||
@@ -47,7 +47,7 @@ export namespace Provider {
|
||||
}),
|
||||
async ({ provider }) => {
|
||||
Actor.assertAdmin()
|
||||
return Database.transaction((tx) =>
|
||||
return Database.use((tx) =>
|
||||
tx
|
||||
.delete(ProviderTable)
|
||||
.where(and(eq(ProviderTable.provider, provider), eq(ProviderTable.workspaceID, Actor.workspace()))),
|
||||
|
||||
12
packages/console/core/src/schema/ip.sql.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { mysqlTable, int, primaryKey, varchar } from "drizzle-orm/mysql-core"
|
||||
import { timestamps } from "../drizzle/types"
|
||||
|
||||
export const IpTable = mysqlTable(
|
||||
"ip",
|
||||
{
|
||||
ip: varchar("ip", { length: 45 }).notNull(),
|
||||
...timestamps,
|
||||
usage: int("usage"),
|
||||
},
|
||||
(table) => [primaryKey({ columns: [table.ip] })],
|
||||
)
|
||||
184
packages/console/core/sst-env.d.ts
vendored
@@ -6,126 +6,130 @@
|
||||
import "sst"
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
ADMIN_SECRET: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ADMIN_SECRET": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AUTH_API_URL: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"AUTH_API_URL": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_ACCESS_KEY_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_ACCESS_KEY_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_SECRET_ACCESS_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_SECRET_ACCESS_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_API_TOKEN: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_API_TOKEN": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_DEFAULT_ACCOUNT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_DEFAULT_ACCOUNT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Console: {
|
||||
type: "sst.cloudflare.SolidStart"
|
||||
url: string
|
||||
"Console": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
Database: {
|
||||
database: string
|
||||
host: string
|
||||
password: string
|
||||
port: number
|
||||
type: "sst.sst.Linkable"
|
||||
username: string
|
||||
"Database": {
|
||||
"database": string
|
||||
"host": string
|
||||
"password": string
|
||||
"port": number
|
||||
"type": "sst.sst.Linkable"
|
||||
"username": string
|
||||
}
|
||||
Desktop: {
|
||||
type: "sst.cloudflare.StaticSite"
|
||||
url: string
|
||||
"Desktop": {
|
||||
"type": "sst.cloudflare.StaticSite"
|
||||
"url": string
|
||||
}
|
||||
EMAILOCTOPUS_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"EMAILOCTOPUS_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_APP_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Enterprise": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
GITHUB_APP_PRIVATE_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_ID_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_PRIVATE_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_SECRET_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_ID_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GOOGLE_CLIENT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_SECRET_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
HONEYCOMB_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GOOGLE_CLIENT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2AccessKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"HONEYCOMB_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2SecretKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2AccessKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_SECRET_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2SecretKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_WEBHOOK_SECRET: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"STRIPE_SECRET_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Web: {
|
||||
type: "sst.cloudflare.Astro"
|
||||
url: string
|
||||
"STRIPE_WEBHOOK_SECRET": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS1: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Web": {
|
||||
"type": "sst.cloudflare.Astro"
|
||||
"url": string
|
||||
}
|
||||
ZEN_MODELS2: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS1": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS3: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS2": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS4: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS3": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
"ZEN_MODELS4": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
}
|
||||
}
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types"
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types";
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
Api: cloudflare.Service
|
||||
AuthApi: cloudflare.Service
|
||||
AuthStorage: cloudflare.KVNamespace
|
||||
Bucket: cloudflare.R2Bucket
|
||||
ConsoleData: cloudflare.R2Bucket
|
||||
EnterpriseStorage: cloudflare.R2Bucket
|
||||
GatewayKv: cloudflare.KVNamespace
|
||||
LogProcessor: cloudflare.Service
|
||||
"Api": cloudflare.Service
|
||||
"AuthApi": cloudflare.Service
|
||||
"AuthStorage": cloudflare.KVNamespace
|
||||
"Bucket": cloudflare.R2Bucket
|
||||
"EnterpriseStorage": cloudflare.R2Bucket
|
||||
"GatewayKv": cloudflare.KVNamespace
|
||||
"LogProcessor": cloudflare.Service
|
||||
"ZenData": cloudflare.R2Bucket
|
||||
}
|
||||
}
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.0.110",
|
||||
"version": "1.0.137",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -194,7 +194,7 @@ export default {
|
||||
// Get workspace
|
||||
await Actor.provide("account", { accountID, email }, async () => {
|
||||
await User.joinInvitedWorkspaces()
|
||||
const workspaces = await Database.transaction(async (tx) =>
|
||||
const workspaces = await Database.use((tx) =>
|
||||
tx
|
||||
.select({ id: WorkspaceTable.id })
|
||||
.from(WorkspaceTable)
|
||||
|
||||
184
packages/console/function/sst-env.d.ts
vendored
@@ -6,126 +6,130 @@
|
||||
import "sst"
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
ADMIN_SECRET: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ADMIN_SECRET": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AUTH_API_URL: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"AUTH_API_URL": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_ACCESS_KEY_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_ACCESS_KEY_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_SECRET_ACCESS_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_SECRET_ACCESS_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_API_TOKEN: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_API_TOKEN": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_DEFAULT_ACCOUNT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_DEFAULT_ACCOUNT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Console: {
|
||||
type: "sst.cloudflare.SolidStart"
|
||||
url: string
|
||||
"Console": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
Database: {
|
||||
database: string
|
||||
host: string
|
||||
password: string
|
||||
port: number
|
||||
type: "sst.sst.Linkable"
|
||||
username: string
|
||||
"Database": {
|
||||
"database": string
|
||||
"host": string
|
||||
"password": string
|
||||
"port": number
|
||||
"type": "sst.sst.Linkable"
|
||||
"username": string
|
||||
}
|
||||
Desktop: {
|
||||
type: "sst.cloudflare.StaticSite"
|
||||
url: string
|
||||
"Desktop": {
|
||||
"type": "sst.cloudflare.StaticSite"
|
||||
"url": string
|
||||
}
|
||||
EMAILOCTOPUS_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"EMAILOCTOPUS_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_APP_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Enterprise": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
GITHUB_APP_PRIVATE_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_ID_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_PRIVATE_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_SECRET_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_ID_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GOOGLE_CLIENT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_SECRET_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
HONEYCOMB_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GOOGLE_CLIENT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2AccessKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"HONEYCOMB_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2SecretKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2AccessKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_SECRET_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2SecretKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_WEBHOOK_SECRET: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"STRIPE_SECRET_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Web: {
|
||||
type: "sst.cloudflare.Astro"
|
||||
url: string
|
||||
"STRIPE_WEBHOOK_SECRET": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS1: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Web": {
|
||||
"type": "sst.cloudflare.Astro"
|
||||
"url": string
|
||||
}
|
||||
ZEN_MODELS2: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS1": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS3: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS2": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS4: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS3": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
"ZEN_MODELS4": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
}
|
||||
}
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types"
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types";
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
Api: cloudflare.Service
|
||||
AuthApi: cloudflare.Service
|
||||
AuthStorage: cloudflare.KVNamespace
|
||||
Bucket: cloudflare.R2Bucket
|
||||
ConsoleData: cloudflare.R2Bucket
|
||||
EnterpriseStorage: cloudflare.R2Bucket
|
||||
GatewayKv: cloudflare.KVNamespace
|
||||
LogProcessor: cloudflare.Service
|
||||
"Api": cloudflare.Service
|
||||
"AuthApi": cloudflare.Service
|
||||
"AuthStorage": cloudflare.KVNamespace
|
||||
"Bucket": cloudflare.R2Bucket
|
||||
"EnterpriseStorage": cloudflare.R2Bucket
|
||||
"GatewayKv": cloudflare.KVNamespace
|
||||
"LogProcessor": cloudflare.Service
|
||||
"ZenData": cloudflare.R2Bucket
|
||||
}
|
||||
}
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.0.110",
|
||||
"version": "1.0.137",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
2
packages/console/mail/sst-env.d.ts
vendored
@@ -6,4 +6,4 @@
|
||||
/// <reference path="../../../sst-env.d.ts" />
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
@@ -2,8 +2,8 @@ import type { KVNamespaceListOptions, KVNamespaceListResult, KVNamespacePutOptio
|
||||
import { Resource as ResourceBase } from "sst"
|
||||
import Cloudflare from "cloudflare"
|
||||
|
||||
export const waitUntil = async (fn: () => Promise<void>) => {
|
||||
await fn()
|
||||
export const waitUntil = async (promise: Promise<any>) => {
|
||||
await promise
|
||||
}
|
||||
|
||||
export const Resource = new Proxy(
|
||||
|
||||
184
packages/console/resource/sst-env.d.ts
vendored
@@ -6,126 +6,130 @@
|
||||
import "sst"
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
ADMIN_SECRET: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ADMIN_SECRET": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AUTH_API_URL: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"AUTH_API_URL": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_ACCESS_KEY_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_ACCESS_KEY_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
AWS_SES_SECRET_ACCESS_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"AWS_SES_SECRET_ACCESS_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_API_TOKEN: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_API_TOKEN": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
CLOUDFLARE_DEFAULT_ACCOUNT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"CLOUDFLARE_DEFAULT_ACCOUNT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Console: {
|
||||
type: "sst.cloudflare.SolidStart"
|
||||
url: string
|
||||
"Console": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
Database: {
|
||||
database: string
|
||||
host: string
|
||||
password: string
|
||||
port: number
|
||||
type: "sst.sst.Linkable"
|
||||
username: string
|
||||
"Database": {
|
||||
"database": string
|
||||
"host": string
|
||||
"password": string
|
||||
"port": number
|
||||
"type": "sst.sst.Linkable"
|
||||
"username": string
|
||||
}
|
||||
Desktop: {
|
||||
type: "sst.cloudflare.StaticSite"
|
||||
url: string
|
||||
"Desktop": {
|
||||
"type": "sst.cloudflare.StaticSite"
|
||||
"url": string
|
||||
}
|
||||
EMAILOCTOPUS_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"EMAILOCTOPUS_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_APP_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Enterprise": {
|
||||
"type": "sst.cloudflare.SolidStart"
|
||||
"url": string
|
||||
}
|
||||
GITHUB_APP_PRIVATE_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_ID_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_APP_PRIVATE_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GITHUB_CLIENT_SECRET_CONSOLE: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_ID_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
GOOGLE_CLIENT_ID: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GITHUB_CLIENT_SECRET_CONSOLE": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
HONEYCOMB_API_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"GOOGLE_CLIENT_ID": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2AccessKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"HONEYCOMB_API_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
R2SecretKey: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2AccessKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_SECRET_KEY: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"R2SecretKey": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
STRIPE_WEBHOOK_SECRET: {
|
||||
type: "sst.sst.Linkable"
|
||||
value: string
|
||||
"STRIPE_SECRET_KEY": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
Web: {
|
||||
type: "sst.cloudflare.Astro"
|
||||
url: string
|
||||
"STRIPE_WEBHOOK_SECRET": {
|
||||
"type": "sst.sst.Linkable"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS1: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"Web": {
|
||||
"type": "sst.cloudflare.Astro"
|
||||
"url": string
|
||||
}
|
||||
ZEN_MODELS2: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS1": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS3: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS2": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
ZEN_MODELS4: {
|
||||
type: "sst.sst.Secret"
|
||||
value: string
|
||||
"ZEN_MODELS3": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
"ZEN_MODELS4": {
|
||||
"type": "sst.sst.Secret"
|
||||
"value": string
|
||||
}
|
||||
}
|
||||
}
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types"
|
||||
// cloudflare
|
||||
import * as cloudflare from "@cloudflare/workers-types";
|
||||
declare module "sst" {
|
||||
export interface Resource {
|
||||
Api: cloudflare.Service
|
||||
AuthApi: cloudflare.Service
|
||||
AuthStorage: cloudflare.KVNamespace
|
||||
Bucket: cloudflare.R2Bucket
|
||||
ConsoleData: cloudflare.R2Bucket
|
||||
EnterpriseStorage: cloudflare.R2Bucket
|
||||
GatewayKv: cloudflare.KVNamespace
|
||||
LogProcessor: cloudflare.Service
|
||||
"Api": cloudflare.Service
|
||||
"AuthApi": cloudflare.Service
|
||||
"AuthStorage": cloudflare.KVNamespace
|
||||
"Bucket": cloudflare.R2Bucket
|
||||
"EnterpriseStorage": cloudflare.R2Bucket
|
||||
"GatewayKv": cloudflare.KVNamespace
|
||||
"LogProcessor": cloudflare.Service
|
||||
"ZenData": cloudflare.R2Bucket
|
||||
}
|
||||
}
|
||||
|
||||
import "sst"
|
||||
export {}
|
||||
export {}
|
||||
2
packages/desktop/bunfig.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[test]
|
||||
preload = ["./happydom.ts"]
|
||||
75
packages/desktop/happydom.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { GlobalRegistrator } from "@happy-dom/global-registrator"
|
||||
|
||||
GlobalRegistrator.register()
|
||||
|
||||
const originalGetContext = HTMLCanvasElement.prototype.getContext
|
||||
// @ts-expect-error - we're overriding with a simplified mock
|
||||
HTMLCanvasElement.prototype.getContext = function (contextType: string, _options?: unknown) {
|
||||
if (contextType === "2d") {
|
||||
return {
|
||||
canvas: this,
|
||||
fillStyle: "#000000",
|
||||
strokeStyle: "#000000",
|
||||
font: "12px monospace",
|
||||
textAlign: "start",
|
||||
textBaseline: "alphabetic",
|
||||
globalAlpha: 1,
|
||||
globalCompositeOperation: "source-over",
|
||||
imageSmoothingEnabled: true,
|
||||
lineWidth: 1,
|
||||
lineCap: "butt",
|
||||
lineJoin: "miter",
|
||||
miterLimit: 10,
|
||||
shadowBlur: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0)",
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 0,
|
||||
fillRect: () => {},
|
||||
strokeRect: () => {},
|
||||
clearRect: () => {},
|
||||
fillText: () => {},
|
||||
strokeText: () => {},
|
||||
measureText: (text: string) => ({ width: text.length * 8 }),
|
||||
drawImage: () => {},
|
||||
save: () => {},
|
||||
restore: () => {},
|
||||
scale: () => {},
|
||||
rotate: () => {},
|
||||
translate: () => {},
|
||||
transform: () => {},
|
||||
setTransform: () => {},
|
||||
resetTransform: () => {},
|
||||
createLinearGradient: () => ({ addColorStop: () => {} }),
|
||||
createRadialGradient: () => ({ addColorStop: () => {} }),
|
||||
createPattern: () => null,
|
||||
beginPath: () => {},
|
||||
closePath: () => {},
|
||||
moveTo: () => {},
|
||||
lineTo: () => {},
|
||||
bezierCurveTo: () => {},
|
||||
quadraticCurveTo: () => {},
|
||||
arc: () => {},
|
||||
arcTo: () => {},
|
||||
ellipse: () => {},
|
||||
rect: () => {},
|
||||
fill: () => {},
|
||||
stroke: () => {},
|
||||
clip: () => {},
|
||||
isPointInPath: () => false,
|
||||
isPointInStroke: () => false,
|
||||
getTransform: () => ({}),
|
||||
getImageData: () => ({
|
||||
data: new Uint8ClampedArray(0),
|
||||
width: 0,
|
||||
height: 0,
|
||||
}),
|
||||
putImageData: () => {},
|
||||
createImageData: () => ({
|
||||
data: new Uint8ClampedArray(0),
|
||||
width: 0,
|
||||
height: 0,
|
||||
}),
|
||||
} as unknown as CanvasRenderingContext2D
|
||||
}
|
||||
return originalGetContext.call(this, contextType as "2d", _options)
|
||||
}
|
||||
@@ -3,9 +3,16 @@
|
||||
<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/svg+xml" href="/favicon.svg" />
|
||||
<title>OpenCode</title>
|
||||
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<meta name="theme-color" content="#F8F7F7" />
|
||||
<meta name="theme-color" content="#131010" media="(prefers-color-scheme: dark)" />
|
||||
<meta property="og:image" content="/social-share.png" />
|
||||
<meta property="twitter:image" content="/social-share.png" />
|
||||
</head>
|
||||
<body class="antialiased overscroll-none select-none text-12-regular">
|
||||
<script>
|
||||
@@ -16,6 +23,6 @@
|
||||
</script>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script src="/src/index.tsx" type="module"></script>
|
||||
<script src="/src/entry.tsx" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.0.110",
|
||||
"version": "1.0.137",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./vite": "./vite.js"
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsgo --noEmit",
|
||||
"start": "vite",
|
||||
@@ -12,8 +16,10 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@happy-dom/global-registrator": "20.0.11",
|
||||
"@tailwindcss/vite": "catalog:",
|
||||
"@tsconfig/bun": "1.0.9",
|
||||
"@types/bun": "catalog:",
|
||||
"@types/luxon": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@typescript/native-preview": "catalog:",
|
||||
@@ -33,11 +39,13 @@
|
||||
"@solid-primitives/resize-observer": "2.1.3",
|
||||
"@solid-primitives/scroll": "2.1.3",
|
||||
"@solid-primitives/storage": "4.3.3",
|
||||
"@solid-primitives/websocket": "1.3.1",
|
||||
"@solidjs/meta": "catalog:",
|
||||
"@solidjs/router": "catalog:",
|
||||
"@thisbeyond/solid-dnd": "0.7.5",
|
||||
"diff": "catalog:",
|
||||
"fuzzysort": "catalog:",
|
||||
"ghostty-web": "0.3.0",
|
||||
"luxon": "catalog:",
|
||||
"marked": "16.2.0",
|
||||
"marked-shiki": "1.2.1",
|
||||
|
||||
1
packages/desktop/public/apple-touch-icon.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/favicon/apple-touch-icon.png
|
||||
1
packages/desktop/public/favicon-96x96.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/favicon/favicon-96x96.png
|
||||
1
packages/desktop/public/favicon.ico
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/favicon/favicon.ico
|
||||
1
packages/desktop/public/site.webmanifest
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/favicon/site.webmanifest
|
||||
1
packages/desktop/public/social-share-zen.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/images/social-share-zen.png
|
||||
1
packages/desktop/public/social-share.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/images/social-share.png
|
||||
1
packages/desktop/public/web-app-manifest-192x192.png
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ui/src/assets/favicon/web-app-manifest-192x192.png
|
||||