Compare commits
491
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6a3be31de | ||
|
|
d16c8c9f0f | ||
|
|
fffe20cbe5 | ||
|
|
f6da3c467b | ||
|
|
c0d9f21c0f | ||
|
|
a67b616139 | ||
|
|
2991547974 | ||
|
|
b59def2e4a | ||
|
|
d842353f39 | ||
|
|
d20ef569de | ||
|
|
ca2b871810 | ||
|
|
23ea8ba1ce | ||
|
|
c417fec246 | ||
|
|
5413b16b57 | ||
|
|
43c021ed80 | ||
|
|
3b005d29d7 | ||
|
|
635f70f477 | ||
|
|
adbb6037ac | ||
|
|
598d6d00e4 | ||
|
|
cf934357c9 | ||
|
|
8063e645c7 | ||
|
|
8ab206b443 | ||
|
|
ec5c96e10d | ||
|
|
d2a61290b9 | ||
|
|
10faf9e717 | ||
|
|
cba239bc8f | ||
|
|
6f5e3ddfb3 | ||
|
|
d412ba264a | ||
|
|
9780f2b792 | ||
|
|
5aa2078852 | ||
|
|
eb975bb89c | ||
|
|
9479fe3ce6 | ||
|
|
4393cf8dbe | ||
|
|
447a4ca8c3 | ||
|
|
40ac2549ff | ||
|
|
a9c56b813a | ||
|
|
b1b73c9deb | ||
|
|
774377330b | ||
|
|
e7a157ef8f | ||
|
|
3989b9fc7f | ||
|
|
8bfcdf4831 | ||
|
|
3632ba3785 | ||
|
|
b7b3824d76 | ||
|
|
b12efb2023 | ||
|
|
bd91cf220c | ||
|
|
9eb6731c21 | ||
|
|
11373755d9 | ||
|
|
00b5e9f6ca | ||
|
|
6b3f424e4d | ||
|
|
e7dfeec9c4 | ||
|
|
97893bd7e6 | ||
|
|
bfefdb3752 | ||
|
|
12b79c581e | ||
|
|
ac9b4c7ebf | ||
|
|
208af232ff | ||
|
|
600c6b4973 | ||
|
|
61007a9b94 | ||
|
|
52fe1a5ac5 | ||
|
|
468927e06a | ||
|
|
61562dd9f0 | ||
|
|
c86dd91310 | ||
|
|
9c85a37811 | ||
|
|
51bba6e634 | ||
|
|
e1089bc5de | ||
|
|
618c654aa0 | ||
|
|
4703e859bd | ||
|
|
a1dc4ebbe4 | ||
|
|
e4e6096510 | ||
|
|
c472734933 | ||
|
|
9d068c20bb | ||
|
|
48e4f2f45d | ||
|
|
bbf4574476 | ||
|
|
8bad513140 | ||
|
|
1ff5d888c2 | ||
|
|
5d25758400 | ||
|
|
16fdc90976 | ||
|
|
793542230f | ||
|
|
9de1242d9b | ||
|
|
b3afa84058 | ||
|
|
024a10bbb5 | ||
|
|
bef9ac96e2 | ||
|
|
24bb293136 | ||
|
|
45180104fe | ||
|
|
edd86e3fb7 | ||
|
|
4a72d57534 | ||
|
|
0068cb305f | ||
|
|
90044196bf | ||
|
|
963a926db2 | ||
|
|
0d3d48bb59 | ||
|
|
66eaba4bdc | ||
|
|
21b6e5404e | ||
|
|
a0fe59ab75 | ||
|
|
81ebf56cf1 | ||
|
|
429708e3d5 | ||
|
|
d50f825c6d | ||
|
|
47bfae52c0 | ||
|
|
52cf9e3423 | ||
|
|
a9b6debfa2 | ||
|
|
d6bf475749 | ||
|
|
f22580e943 | ||
|
|
6d98db57c7 | ||
|
|
59f127a250 | ||
|
|
3068e7dcf7 | ||
|
|
f83d62191a | ||
|
|
3b72857124 | ||
|
|
68cd105d9d | ||
|
|
e09af2cb4b | ||
|
|
14bd3b1d30 | ||
|
|
3a9c2152f7 | ||
|
|
7283bfa480 | ||
|
|
37d5099728 | ||
|
|
d45fc030b2 | ||
|
|
c7042c807f | ||
|
|
202f6f1be9 | ||
|
|
759635eefa | ||
|
|
a9981441ae | ||
|
|
71302de4f1 | ||
|
|
333b8e907b | ||
|
|
13f319b64f | ||
|
|
b573eadd9e | ||
|
|
50bfff89c0 | ||
|
|
fc5fc2c570 | ||
|
|
4069999b78 | ||
|
|
5ba9b47b3c | ||
|
|
7c0cc94023 | ||
|
|
3ed1bd2e8e | ||
|
|
ce6436280a | ||
|
|
e49204bd33 | ||
|
|
856c87d05c | ||
|
|
de35c3fb84 | ||
|
|
4359719f9a | ||
|
|
5e13527416 | ||
|
|
aba94c658f | ||
|
|
6e318ba567 | ||
|
|
ddddecf88a | ||
|
|
16cb77c094 | ||
|
|
a5564f730e | ||
|
|
a15c97bbfe | ||
|
|
a398eed8b8 | ||
|
|
a10fd8ca5c | ||
|
|
ff7513238b | ||
|
|
af1cd60d3e | ||
|
|
c66def2049 | ||
|
|
008ccb4729 | ||
|
|
bc232045a1 | ||
|
|
16cab556df | ||
|
|
66148df74b | ||
|
|
4611e08f09 | ||
|
|
bf6204f577 | ||
|
|
17cde9feb7 | ||
|
|
7eccbdc4ac | ||
|
|
ab072290fc | ||
|
|
ad9d83748c | ||
|
|
55b57e1aae | ||
|
|
21b7877beb | ||
|
|
de50234a1a | ||
|
|
d60102ba52 | ||
|
|
066a876f3d | ||
|
|
c07a241ca8 | ||
|
|
0a2fffa9b5 | ||
|
|
bdfa213ccf | ||
|
|
7f0b2ce1ac | ||
|
|
0a2d7af179 | ||
|
|
37652f48fb | ||
|
|
8b19c6c7e4 | ||
|
|
a5365ce294 | ||
|
|
f4a4514a9f | ||
|
|
154006469c | ||
|
|
a1214fff2e | ||
|
|
9fd43ec616 | ||
|
|
5731c268b6 | ||
|
|
f4d892d4e1 | ||
|
|
10b3702938 | ||
|
|
e96442310c | ||
|
|
5c722bf8c4 | ||
|
|
58cc5cdf2a | ||
|
|
3c6dcad2af | ||
|
|
2535f9febf | ||
|
|
25678fa504 | ||
|
|
d7f4f3ec1f | ||
|
|
16ccb39459 | ||
|
|
f8630fb188 | ||
|
|
72e604744d | ||
|
|
832be6e7eb | ||
|
|
8ba48ed71d | ||
|
|
cf266f6162 | ||
|
|
1e6589526d | ||
|
|
f6b3ffaf64 | ||
|
|
5d765d63d4 | ||
|
|
0e12dd62a3 | ||
|
|
2b957b5d1c | ||
|
|
31c7a0157c | ||
|
|
e728b94bca | ||
|
|
49040c0130 | ||
|
|
0d05238ee6 | ||
|
|
9b8a7da1e6 | ||
|
|
61fd21182c | ||
|
|
487c2b5e76 | ||
|
|
0e4703b227 | ||
|
|
84e0232bd5 | ||
|
|
35fbb011b2 | ||
|
|
6527a123f0 | ||
|
|
0377cfd37c | ||
|
|
edc933d816 | ||
|
|
0d608f6014 | ||
|
|
69a45ef7d7 | ||
|
|
1056b36eae | ||
|
|
35c737ac68 | ||
|
|
725a2c2e95 | ||
|
|
c724d2392f | ||
|
|
f5230d1f02 | ||
|
|
078111bd96 | ||
|
|
736f8882f5 | ||
|
|
37cf365927 | ||
|
|
b939470302 | ||
|
|
ef4b2baedc | ||
|
|
64d28ea457 | ||
|
|
2520780846 | ||
|
|
986c60353e | ||
|
|
5fc26c958a | ||
|
|
c1cf9cda6a | ||
|
|
10d376eab2 | ||
|
|
53fc8a861b | ||
|
|
1d8330331c | ||
|
|
7a03c7fe38 | ||
|
|
09bd32169c | ||
|
|
7ec32f834e | ||
|
|
205492c7e8 | ||
|
|
4c2e888709 | ||
|
|
c78fd097d1 | ||
|
|
340966195b | ||
|
|
92604b391b | ||
|
|
0c51feb9c2 | ||
|
|
d0b4169a6b | ||
|
|
1fc6c6fb2a | ||
|
|
14f9b95557 | ||
|
|
d3bf1fa1fa | ||
|
|
a8836c5615 | ||
|
|
779a27693a | ||
|
|
829d86840a | ||
|
|
e225294dd4 | ||
|
|
a673e3650d | ||
|
|
ff462dfd7a | ||
|
|
73443585e5 | ||
|
|
609ab069a9 | ||
|
|
ec3579d7cb | ||
|
|
f80a3fea31 | ||
|
|
43a8d1b1ae | ||
|
|
09fa84ccfc | ||
|
|
b981f0a205 | ||
|
|
767038afc3 | ||
|
|
a7774115c5 | ||
|
|
288bc88e40 | ||
|
|
6d36dbf9de | ||
|
|
4ab4baf3a4 | ||
|
|
90f05eb9c2 | ||
|
|
b63b6d04c6 | ||
|
|
8addaa7e08 | ||
|
|
a96bf8e62d | ||
|
|
c8bda598f5 | ||
|
|
c857cff585 | ||
|
|
fd9d2db755 | ||
|
|
b19fd14f80 | ||
|
|
715265de4b | ||
|
|
2048f32491 | ||
|
|
2d7ba43a21 | ||
|
|
bd198d8550 | ||
|
|
cbffbcdd3d | ||
|
|
2be8b2269f | ||
|
|
a0f469095c | ||
|
|
0ccb26df94 | ||
|
|
71fd5966ad | ||
|
|
c02230de4f | ||
|
|
aa2e2c76c0 | ||
|
|
7c2d4ee79a | ||
|
|
e3a2728fa3 | ||
|
|
18260b037b | ||
|
|
ad83dd3ad9 | ||
|
|
6f37315cd1 | ||
|
|
d81dce6a82 | ||
|
|
0bd11e970b | ||
|
|
7e29e1dd23 | ||
|
|
491a2adf8d | ||
|
|
c07d6487a8 | ||
|
|
9990e84d37 | ||
|
|
0b86adbe99 | ||
|
|
834a2c09d5 | ||
|
|
f13c17e654 | ||
|
|
a0611d92e4 | ||
|
|
c1fa257a92 | ||
|
|
7fd81dd93e | ||
|
|
d554e7aaef | ||
|
|
0b001c3e80 | ||
|
|
53b7cb62c4 | ||
|
|
c5e096c76a | ||
|
|
e1fc4a756b | ||
|
|
e5bc4cbbcf | ||
|
|
459d5ec19b | ||
|
|
8baa222621 | ||
|
|
ce1397cc34 | ||
|
|
dc7c5ced4c | ||
|
|
b8e8fe7e31 | ||
|
|
890085758f | ||
|
|
85f15893bc | ||
|
|
98be75b17c | ||
|
|
b5cc27b8ea | ||
|
|
05937b52cc | ||
|
|
62b82570e1 | ||
|
|
4bf75c0b44 | ||
|
|
a8a06c4983 | ||
|
|
b0b7fd143b | ||
|
|
140498eb4f | ||
|
|
ca5126e24d | ||
|
|
fb2b3e567c | ||
|
|
c672a1963b | ||
|
|
54bff6b120 | ||
|
|
ab3f198fab | ||
|
|
0057ef6336 | ||
|
|
4f604b3839 | ||
|
|
a20489584e | ||
|
|
a6b066bd47 | ||
|
|
37fdcac05a | ||
|
|
299bf1dca8 | ||
|
|
d685aa38ef | ||
|
|
995b23787c | ||
|
|
ed8e663e13 | ||
|
|
38cee3b848 | ||
|
|
6d116d4b54 | ||
|
|
7c4f111b34 | ||
|
|
f2fac29270 | ||
|
|
12892f0e12 | ||
|
|
9714a3558e | ||
|
|
e49a1d1f39 | ||
|
|
528565510d | ||
|
|
36cfda933d | ||
|
|
ecf5040966 | ||
|
|
7d56603c26 | ||
|
|
02b7cc8313 | ||
|
|
c9a52c9a85 | ||
|
|
dea668b0ea | ||
|
|
1bc3e92376 | ||
|
|
3f5acc3dff | ||
|
|
0588011476 | ||
|
|
bba72c82ae | ||
|
|
e95181a551 | ||
|
|
74e8c2e50f | ||
|
|
cdabafa264 | ||
|
|
0a92af60a0 | ||
|
|
c7808a4b01 | ||
|
|
7f978e07ff | ||
|
|
a4ae1bb9eb | ||
|
|
96a39803cc | ||
|
|
16f8f20b31 | ||
|
|
06b1684ddb | ||
|
|
c6e830c954 | ||
|
|
fc78c28df6 | ||
|
|
930a1bf358 | ||
|
|
6cf7f18cc9 | ||
|
|
3f59570ee6 | ||
|
|
304e956b5d | ||
|
|
538eaa42aa | ||
|
|
67c41fd389 | ||
|
|
83ea19770a | ||
|
|
3ace8543b2 | ||
|
|
eb855e1e31 | ||
|
|
5e53f054c6 | ||
|
|
5d5e184329 | ||
|
|
2fbb49ac30 | ||
|
|
c56b407e1d | ||
|
|
bdaa0e8b8c | ||
|
|
4e549b1c05 | ||
|
|
7be8e16c33 | ||
|
|
d1588f93a1 | ||
|
|
576696a370 | ||
|
|
2c6f9043e8 | ||
|
|
9f771ef0ae | ||
|
|
356715f67d | ||
|
|
540421267a | ||
|
|
e253398936 | ||
|
|
ee87e1f139 | ||
|
|
8887616457 | ||
|
|
905c034885 | ||
|
|
92f7c4943f | ||
|
|
10bde356b1 | ||
|
|
f7cc46cd9f | ||
|
|
d9ffe07391 | ||
|
|
c0702ed8bd | ||
|
|
b927b9dca6 | ||
|
|
4b7231be68 | ||
|
|
70a6fe96ea | ||
|
|
6e5971dff2 | ||
|
|
d48d6b3577 | ||
|
|
4b1668c3ef | ||
|
|
d85eb1b880 | ||
|
|
9637d70407 | ||
|
|
cfbbdc2e14 | ||
|
|
feb65201f6 | ||
|
|
f1f07a56d8 | ||
|
|
0fe313bd87 | ||
|
|
1fd676528d | ||
|
|
0a2801444b | ||
|
|
c9adbc7c21 | ||
|
|
ba8de38435 | ||
|
|
8166612467 | ||
|
|
4d20e1c3c6 | ||
|
|
4bb7ea9127 | ||
|
|
969af4d541 | ||
|
|
271b679058 | ||
|
|
83b16cb18e | ||
|
|
431ffc94f5 | ||
|
|
47b4cc6d53 | ||
|
|
ce9b758d0a | ||
|
|
f8a1a0b26f | ||
|
|
6ecaf83f76 | ||
|
|
30b1ae5d4b | ||
|
|
9cd465f9c0 | ||
|
|
1747979568 | ||
|
|
062023fa06 | ||
|
|
954a796b8a | ||
|
|
34ff87d504 | ||
|
|
16357e8041 | ||
|
|
dabb1aa719 | ||
|
|
7af3380455 | ||
|
|
dcaa90808e | ||
|
|
01705fd467 | ||
|
|
006f3bdeb6 | ||
|
|
1d43b4e6d7 | ||
|
|
8cef7940fe | ||
|
|
b2dd9fdfdf | ||
|
|
b82a52cb85 | ||
|
|
7294d86778 | ||
|
|
3bb3f4f2c9 | ||
|
|
d31f97343c | ||
|
|
536d10e5ab | ||
|
|
9885c716f3 | ||
|
|
39461fbbce | ||
|
|
1a2b3701f2 | ||
|
|
0a395d8783 | ||
|
|
79bb22a573 | ||
|
|
4271df96d2 | ||
|
|
aa07be09e1 | ||
|
|
5d6bdca6d0 | ||
|
|
58bbe9e689 | ||
|
|
b5a035ceab | ||
|
|
b3c6d0b08a | ||
|
|
090d27df11 | ||
|
|
b374a6cac9 | ||
|
|
73cd8a334c | ||
|
|
b46c3f2a26 | ||
|
|
45fabec091 | ||
|
|
a96365fd81 | ||
|
|
5f7e1e099b | ||
|
|
d462e380f4 | ||
|
|
c5a558f3da | ||
|
|
7f51b181d4 | ||
|
|
7adbc3ad44 | ||
|
|
89922a8598 | ||
|
|
3a1d1a6284 | ||
|
|
4463d319c9 | ||
|
|
c6eea0343d | ||
|
|
e317e7e481 | ||
|
|
287855336d | ||
|
|
d55f4f3322 | ||
|
|
b708d0ecec | ||
|
|
afb831c93c | ||
|
|
14397651b5 | ||
|
|
e5804f64f9 | ||
|
|
ce7b73170f | ||
|
|
9554abb56e | ||
|
|
d0f5c825bd | ||
|
|
9f603e39a6 | ||
|
|
da51c9dfac | ||
|
|
9e04ff013c | ||
|
|
6bfccace0c | ||
|
|
b25d4f9dfb | ||
|
|
d1962ca5a7 | ||
|
|
25f31f3096 | ||
|
|
11a6f0886e | ||
|
|
3ba7e243d0 | ||
|
|
a2ab019317 | ||
|
|
21957406ff | ||
|
|
61c4747fbe | ||
|
|
957c43aa09 | ||
|
|
96c57418f3 | ||
|
|
b8c51e307f | ||
|
|
6791233ca0 | ||
|
|
cd6072ec58 | ||
|
|
017e42bbcd | ||
|
|
7088bfabd7 | ||
|
|
dbdbfb8543 | ||
|
|
521803aaa3 |
@@ -13,9 +13,9 @@ runs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.bun
|
path: ~/.bun
|
||||||
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lockb', 'bun.lock') }}
|
key: ${{ runner.os }}-bun-${{ hashFiles('package.json') }}-${{ hashFiles('bun.lockb', 'bun.lock') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-bun-
|
${{ runner.os }}-bun-${{ hashFiles('package.json') }}-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: bun install
|
run: bun install
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
#
|
||||||
|
# This file is intentionally in the wrong dir, will move and add later....
|
||||||
|
#
|
||||||
|
|
||||||
name: Guidelines Check
|
name: Guidelines Check
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -28,14 +28,14 @@ jobs:
|
|||||||
const versionPattern = /[v]?1\.0\./i;
|
const versionPattern = /[v]?1\.0\./i;
|
||||||
const isVersionRelated = versionPattern.test(title) || versionPattern.test(description);
|
const isVersionRelated = versionPattern.test(title) || versionPattern.test(description);
|
||||||
|
|
||||||
|
// Check for "nix" keyword
|
||||||
|
const nixPattern = /\bnix\b/i;
|
||||||
|
const isNixRelated = nixPattern.test(title) || nixPattern.test(description);
|
||||||
|
|
||||||
|
const labels = [];
|
||||||
|
|
||||||
if (isWebRelated) {
|
if (isWebRelated) {
|
||||||
// Add web label
|
labels.push('web');
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issue.number,
|
|
||||||
labels: ['web']
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assign to adamdotdevin
|
// Assign to adamdotdevin
|
||||||
await github.rest.issues.addAssignees({
|
await github.rest.issues.addAssignees({
|
||||||
@@ -46,10 +46,18 @@ jobs:
|
|||||||
});
|
});
|
||||||
} else if (isVersionRelated) {
|
} else if (isVersionRelated) {
|
||||||
// Only add opentui if NOT web-related
|
// Only add opentui if NOT web-related
|
||||||
|
labels.push('opentui');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNixRelated) {
|
||||||
|
labels.push('nix');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labels.length > 0) {
|
||||||
await github.rest.issues.addLabels({
|
await github.rest.issues.addLabels({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
issue_number: issue.number,
|
issue_number: issue.number,
|
||||||
labels: ['opentui']
|
labels: labels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
"webfetch": "deny"
|
"webfetch": "deny"
|
||||||
}
|
}
|
||||||
run: |
|
run: |
|
||||||
opencode run -m anthropic/claude-sonnet-4-20250514 "A new issue has been created:'
|
opencode run -m opencode/claude-haiku-4-5 "A new issue has been created:'
|
||||||
|
|
||||||
Issue number:
|
Issue number:
|
||||||
${{ github.event.issue.number }}
|
${{ github.event.issue.number }}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ on:
|
|||||||
- major
|
- major
|
||||||
- minor
|
- minor
|
||||||
- patch
|
- patch
|
||||||
|
version:
|
||||||
|
description: "Override version (optional)"
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
|
||||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|
||||||
@@ -62,6 +66,7 @@ jobs:
|
|||||||
./script/publish.ts
|
./script/publish.ts
|
||||||
env:
|
env:
|
||||||
OPENCODE_BUMP: ${{ inputs.bump }}
|
OPENCODE_BUMP: ${{ inputs.bump }}
|
||||||
|
OPENCODE_VERSION: ${{ inputs.version }}
|
||||||
OPENCODE_CHANNEL: latest
|
OPENCODE_CHANNEL: latest
|
||||||
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- dev
|
||||||
- opentui
|
- fix-snapshot-2
|
||||||
- v0
|
- v0
|
||||||
|
|
||||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: "sync-zed-extension"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
zed:
|
||||||
|
name: Release Zed Extension
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-bun
|
||||||
|
|
||||||
|
- name: Get version tag
|
||||||
|
id: get_tag
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "release" ]; then
|
||||||
|
TAG="${{ github.event.release.tag_name }}"
|
||||||
|
else
|
||||||
|
TAG=$(git tag --list 'v[0-9]*.*' --sort=-version:refname | head -n 1)
|
||||||
|
fi
|
||||||
|
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||||
|
echo "Using tag: ${TAG}"
|
||||||
|
|
||||||
|
- name: Sync Zed extension
|
||||||
|
run: |
|
||||||
|
./script/sync-zed.ts ${{ steps.get_tag.outputs.tag }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||||
@@ -28,3 +28,9 @@ jobs:
|
|||||||
bun turbo test
|
bun turbo test
|
||||||
env:
|
env:
|
||||||
CI: true
|
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
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
name: Update Nix Hashes
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "bun.lock"
|
||||||
|
- "package.json"
|
||||||
|
- "packages/*/package.json"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "bun.lock"
|
||||||
|
- "package.json"
|
||||||
|
- "packages/*/package.json"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
SYSTEM: x86_64-linux
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup Nix
|
||||||
|
uses: DeterminateSystems/nix-installer-action@v20
|
||||||
|
|
||||||
|
- name: Configure git
|
||||||
|
run: |
|
||||||
|
git config --global user.email "action@github.com"
|
||||||
|
git config --global user.name "Github Action"
|
||||||
|
|
||||||
|
- name: Update flake.lock
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
nix flake update
|
||||||
|
|
||||||
|
- name: Update node_modules hash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
nix/scripts/update-hashes.sh
|
||||||
|
|
||||||
|
- name: Commit hash changes
|
||||||
|
env:
|
||||||
|
TARGET_BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
summarize() {
|
||||||
|
local status="$1"
|
||||||
|
{
|
||||||
|
echo "### Nix Hash Update"
|
||||||
|
echo ""
|
||||||
|
echo "- ref: ${GITHUB_REF_NAME}"
|
||||||
|
echo "- status: ${status}"
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then
|
||||||
|
echo "- run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
fi
|
||||||
|
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
}
|
||||||
|
|
||||||
|
FILES=(flake.lock flake.nix nix/node-modules.nix nix/hashes.json)
|
||||||
|
STATUS="$(git status --short -- "${FILES[@]}" || true)"
|
||||||
|
if [ -z "$STATUS" ]; then
|
||||||
|
summarize "no changes"
|
||||||
|
echo "No changes to tracked Nix files. Hashes are already up to date."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git add "${FILES[@]}"
|
||||||
|
git commit -m "Update Nix flake.lock and hashes"
|
||||||
|
|
||||||
|
BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}"
|
||||||
|
git push origin HEAD:"$BRANCH"
|
||||||
|
|
||||||
|
summarize "committed $(git rev-parse --short HEAD)"
|
||||||
@@ -13,3 +13,8 @@ dist
|
|||||||
.turbo
|
.turbo
|
||||||
**/.serena
|
**/.serena
|
||||||
.serena/
|
.serena/
|
||||||
|
/result
|
||||||
|
refs
|
||||||
|
Session.vim
|
||||||
|
opencode.json
|
||||||
|
a.out
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Git commit and push
|
description: Git commit and push
|
||||||
|
subtask: true
|
||||||
---
|
---
|
||||||
|
|
||||||
commit and push
|
commit and push
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
description: "Find issue(s) on github"
|
||||||
|
model: opencode/claude-haiku-4-5
|
||||||
|
---
|
||||||
|
|
||||||
|
Search through existing issues in sst/opencode using the gh cli to find issues matching this query:
|
||||||
|
|
||||||
|
$ARGUMENTS
|
||||||
|
|
||||||
|
Consider:
|
||||||
|
|
||||||
|
1. Similar titles or descriptions
|
||||||
|
2. Same error messages or symptoms
|
||||||
|
3. Related functionality or components
|
||||||
|
4. Similar feature requests
|
||||||
|
|
||||||
|
Please list any matching issues with:
|
||||||
|
|
||||||
|
- Issue number and title
|
||||||
|
- Brief explanation of why it matches the query
|
||||||
|
- Link to the issue
|
||||||
|
|
||||||
|
If no clear matches are found, say so.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"plugin": ["opencode-openai-codex-auth"],
|
||||||
|
"provider": {
|
||||||
|
"opencode": {
|
||||||
|
"options": {
|
||||||
|
// "baseURL": "http://localhost:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/theme.json",
|
||||||
|
"defs": {
|
||||||
|
"nord0": "#2E3440",
|
||||||
|
"nord1": "#3B4252",
|
||||||
|
"nord2": "#434C5E",
|
||||||
|
"nord3": "#4C566A",
|
||||||
|
"nord4": "#D8DEE9",
|
||||||
|
"nord5": "#E5E9F0",
|
||||||
|
"nord6": "#ECEFF4",
|
||||||
|
"nord7": "#8FBCBB",
|
||||||
|
"nord8": "#88C0D0",
|
||||||
|
"nord9": "#81A1C1",
|
||||||
|
"nord10": "#5E81AC",
|
||||||
|
"nord11": "#BF616A",
|
||||||
|
"nord12": "#D08770",
|
||||||
|
"nord13": "#EBCB8B",
|
||||||
|
"nord14": "#A3BE8C",
|
||||||
|
"nord15": "#B48EAD"
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"primary": {
|
||||||
|
"dark": "nord8",
|
||||||
|
"light": "nord10"
|
||||||
|
},
|
||||||
|
"secondary": {
|
||||||
|
"dark": "nord9",
|
||||||
|
"light": "nord9"
|
||||||
|
},
|
||||||
|
"accent": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"dark": "nord11",
|
||||||
|
"light": "nord11"
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"dark": "nord12",
|
||||||
|
"light": "nord12"
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"dark": "nord14",
|
||||||
|
"light": "nord14"
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"dark": "nord8",
|
||||||
|
"light": "nord10"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"dark": "nord4",
|
||||||
|
"light": "nord0"
|
||||||
|
},
|
||||||
|
"textMuted": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord1"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"dark": "nord0",
|
||||||
|
"light": "nord6"
|
||||||
|
},
|
||||||
|
"backgroundPanel": {
|
||||||
|
"dark": "nord1",
|
||||||
|
"light": "nord5"
|
||||||
|
},
|
||||||
|
"backgroundElement": {
|
||||||
|
"dark": "nord1",
|
||||||
|
"light": "nord4"
|
||||||
|
},
|
||||||
|
"border": {
|
||||||
|
"dark": "nord2",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"borderActive": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord2"
|
||||||
|
},
|
||||||
|
"borderSubtle": {
|
||||||
|
"dark": "nord2",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"diffAdded": {
|
||||||
|
"dark": "nord14",
|
||||||
|
"light": "nord14"
|
||||||
|
},
|
||||||
|
"diffRemoved": {
|
||||||
|
"dark": "nord11",
|
||||||
|
"light": "nord11"
|
||||||
|
},
|
||||||
|
"diffContext": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"diffHunkHeader": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"diffHighlightAdded": {
|
||||||
|
"dark": "nord14",
|
||||||
|
"light": "nord14"
|
||||||
|
},
|
||||||
|
"diffHighlightRemoved": {
|
||||||
|
"dark": "nord11",
|
||||||
|
"light": "nord11"
|
||||||
|
},
|
||||||
|
"diffAddedBg": {
|
||||||
|
"dark": "#3B4252",
|
||||||
|
"light": "#E5E9F0"
|
||||||
|
},
|
||||||
|
"diffRemovedBg": {
|
||||||
|
"dark": "#3B4252",
|
||||||
|
"light": "#E5E9F0"
|
||||||
|
},
|
||||||
|
"diffContextBg": {
|
||||||
|
"dark": "nord1",
|
||||||
|
"light": "nord5"
|
||||||
|
},
|
||||||
|
"diffLineNumber": {
|
||||||
|
"dark": "nord2",
|
||||||
|
"light": "nord4"
|
||||||
|
},
|
||||||
|
"diffAddedLineNumberBg": {
|
||||||
|
"dark": "#3B4252",
|
||||||
|
"light": "#E5E9F0"
|
||||||
|
},
|
||||||
|
"diffRemovedLineNumberBg": {
|
||||||
|
"dark": "#3B4252",
|
||||||
|
"light": "#E5E9F0"
|
||||||
|
},
|
||||||
|
"markdownText": {
|
||||||
|
"dark": "nord4",
|
||||||
|
"light": "nord0"
|
||||||
|
},
|
||||||
|
"markdownHeading": {
|
||||||
|
"dark": "nord8",
|
||||||
|
"light": "nord10"
|
||||||
|
},
|
||||||
|
"markdownLink": {
|
||||||
|
"dark": "nord9",
|
||||||
|
"light": "nord9"
|
||||||
|
},
|
||||||
|
"markdownLinkText": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"markdownCode": {
|
||||||
|
"dark": "nord14",
|
||||||
|
"light": "nord14"
|
||||||
|
},
|
||||||
|
"markdownBlockQuote": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"markdownEmph": {
|
||||||
|
"dark": "nord12",
|
||||||
|
"light": "nord12"
|
||||||
|
},
|
||||||
|
"markdownStrong": {
|
||||||
|
"dark": "nord13",
|
||||||
|
"light": "nord13"
|
||||||
|
},
|
||||||
|
"markdownHorizontalRule": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"markdownListItem": {
|
||||||
|
"dark": "nord8",
|
||||||
|
"light": "nord10"
|
||||||
|
},
|
||||||
|
"markdownListEnumeration": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"markdownImage": {
|
||||||
|
"dark": "nord9",
|
||||||
|
"light": "nord9"
|
||||||
|
},
|
||||||
|
"markdownImageText": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"markdownCodeBlock": {
|
||||||
|
"dark": "nord4",
|
||||||
|
"light": "nord0"
|
||||||
|
},
|
||||||
|
"syntaxComment": {
|
||||||
|
"dark": "nord3",
|
||||||
|
"light": "nord3"
|
||||||
|
},
|
||||||
|
"syntaxKeyword": {
|
||||||
|
"dark": "nord9",
|
||||||
|
"light": "nord9"
|
||||||
|
},
|
||||||
|
"syntaxFunction": {
|
||||||
|
"dark": "nord8",
|
||||||
|
"light": "nord8"
|
||||||
|
},
|
||||||
|
"syntaxVariable": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"syntaxString": {
|
||||||
|
"dark": "nord14",
|
||||||
|
"light": "nord14"
|
||||||
|
},
|
||||||
|
"syntaxNumber": {
|
||||||
|
"dark": "nord15",
|
||||||
|
"light": "nord15"
|
||||||
|
},
|
||||||
|
"syntaxType": {
|
||||||
|
"dark": "nord7",
|
||||||
|
"light": "nord7"
|
||||||
|
},
|
||||||
|
"syntaxOperator": {
|
||||||
|
"dark": "nord9",
|
||||||
|
"light": "nord9"
|
||||||
|
},
|
||||||
|
"syntaxPunctuation": {
|
||||||
|
"dark": "nord4",
|
||||||
|
"light": "nord0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "bun",
|
||||||
|
"request": "attach",
|
||||||
|
"name": "opencode (attach)",
|
||||||
|
"url": "ws://localhost:6499/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"oven.bun-vscode"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -42,6 +42,38 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you
|
|||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> After touching `packages/opencode/src/server/server.ts`, run "./packages/sdk/js/script/build.ts" to regenerate the JS sdk.
|
> After touching `packages/opencode/src/server/server.ts`, run "./packages/sdk/js/script/build.ts" to regenerate the JS sdk.
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
The most reliable way to debug OpenCode is to run it manually in a terminal via `bun run --inspect=<url> dev ...` and attach
|
||||||
|
your debugger via that URL. Other methods can result in breakpoints being mapped incorrectly, at least in VSCode (YMMV).
|
||||||
|
|
||||||
|
Caveats:
|
||||||
|
|
||||||
|
- `*.tsx` files won't have their breakpoints correctly mapped. This seems due to Bun currently not supporting source maps on code transformed
|
||||||
|
via `BunPlugin`s (currently necessary due to our dependency on `@opentui/solid`). Currently, the best you can do in terms of debugging `*.tsx`
|
||||||
|
files is writing a `debugger;` statement. Debugging facilities like stepping won't work, but at least you will be informed if a specific code
|
||||||
|
is triggered.
|
||||||
|
- If you want to run the OpenCode TUI and have breakpoints triggered in the server code, you might need to run `bun dev spawn` instead of
|
||||||
|
the usual `bun dev`. This is because `bun dev` runs the server in a worker thread and breakpoints might not work there.
|
||||||
|
|
||||||
|
Other tips and tricks:
|
||||||
|
|
||||||
|
- You might want to use `--inspect-wait` or `--inspect-brk` instead of `--inspect`, depending on your workflow
|
||||||
|
- Specifying `--inspect=ws://localhost:6499/` on every invocation can be tiresome, you may want to `export BUN_OPTIONS=--inspect=ws://localhost:6499/` instead
|
||||||
|
|
||||||
|
#### VSCode Setup
|
||||||
|
|
||||||
|
If you use VSCode, you can use our example configurations [.vscode/settings.example.json](.vscode/settings.example.json) and [.vscode/launch.example.json](.vscode/launch.example.json).
|
||||||
|
|
||||||
|
Some debug methods that can be problematic:
|
||||||
|
|
||||||
|
- Debug configurations with `"request": "launch"` can have breakpoints incorrectly mapped and thus unusable
|
||||||
|
- The same problem arises when running OpenCode in the VSCode `JavaScript Debug Terminal`
|
||||||
|
|
||||||
|
With that said, you may want to try these methods, as they might work for you.
|
||||||
|
|
||||||
## Pull Request Expectations
|
## Pull Request Expectations
|
||||||
|
|
||||||
- Try to keep pull requests small and focused.
|
- Try to keep pull requests small and focused.
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ scoop bucket add extras; scoop install extras/opencode # Windows
|
|||||||
choco install opencode # Windows
|
choco install opencode # Windows
|
||||||
brew install opencode # macOS and Linux
|
brew install opencode # macOS and Linux
|
||||||
paru -S opencode-bin # Arch Linux
|
paru -S opencode-bin # Arch Linux
|
||||||
|
mise use --pin -g ubi:sst/opencode # Any OS
|
||||||
|
nix run nixpkgs#opencode # or github:sst/opencode for latest dev branch
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
@@ -50,6 +52,22 @@ OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bas
|
|||||||
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash
|
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Agents
|
||||||
|
|
||||||
|
OpenCode includes two built-in agents you can switch between,
|
||||||
|
you can switch between these using the `Tab` key.
|
||||||
|
|
||||||
|
- **build** - Default, full access agent for development work
|
||||||
|
- **plan** - Read-only agent for analysis and code exploration
|
||||||
|
- Denies file edits by default
|
||||||
|
- Asks permission before running bash commands
|
||||||
|
- Ideal for exploring unfamiliar codebases or planning changes
|
||||||
|
|
||||||
|
Also, included is a **general** subagent for complex searches and multi-step tasks.
|
||||||
|
This is used internally and can be invoked using `@general` in messages.
|
||||||
|
|
||||||
|
Learn more about [agents](https://opencode.ai/docs/agents).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
For more info on how to configure OpenCode [**head over to our docs**](https://opencode.ai/docs).
|
For more info on how to configure OpenCode [**head over to our docs**](https://opencode.ai/docs).
|
||||||
@@ -58,6 +76,10 @@ For more info on how to configure OpenCode [**head over to our docs**](https://o
|
|||||||
|
|
||||||
If you're interested in contributing to OpenCode, please read our [contributing docs](./CONTRIBUTING.md) before submitting a pull request.
|
If you're interested in contributing to OpenCode, please read our [contributing docs](./CONTRIBUTING.md) before submitting a pull request.
|
||||||
|
|
||||||
|
### Building on OpenCode
|
||||||
|
|
||||||
|
If you are working on a project that's related to OpenCode and is using "opencode" as a part of its name; for example, "opencode-dashboard" or "opencode-mobile", please add a note to your README to clarify that it is not built by the OpenCode team and is not affiliated with us in anyway.
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
#### How is this different than Claude Code?
|
#### How is this different than Claude Code?
|
||||||
@@ -65,7 +87,7 @@ If you're interested in contributing to OpenCode, please read our [contributing
|
|||||||
It's very similar to Claude Code in terms of capability. Here are the key differences:
|
It's very similar to Claude Code in terms of capability. Here are the key differences:
|
||||||
|
|
||||||
- 100% open source
|
- 100% open source
|
||||||
- Not coupled to any provider. Although Anthropic is recommended, OpenCode can be used with OpenAI, Google or even local models. As models evolve the gaps between them will close and pricing will drop so being provider-agnostic is important.
|
- Not coupled to any provider. Although we recommend the models we provide through [OpenCode Zen](https://opencode.ai/zen); OpenCode can be used with Claude, OpenAI, Google or even local models. As models evolve the gaps between them will close and pricing will drop so being provider-agnostic is important.
|
||||||
- Out of the box LSP support
|
- Out of the box LSP support
|
||||||
- A focus on TUI. OpenCode is built by neovim users and the creators of [terminal.shop](https://terminal.shop); we are going to push the limits of what's possible in the terminal.
|
- A focus on TUI. OpenCode is built by neovim users and the creators of [terminal.shop](https://terminal.shop); we are going to push the limits of what's possible in the terminal.
|
||||||
- A client/server architecture. This for example can allow OpenCode to run on your computer, while you can drive it remotely from a mobile app. Meaning that the TUI frontend is just one of the possible clients.
|
- A client/server architecture. This for example can allow OpenCode to run on your computer, while you can drive it remotely from a mobile app. Meaning that the TUI frontend is just one of the possible clients.
|
||||||
|
|||||||
@@ -132,3 +132,17 @@
|
|||||||
| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) |
|
| 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-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-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) |
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
"@tsconfig/bun": "catalog:",
|
"@tsconfig/bun": "catalog:",
|
||||||
"husky": "9.1.7",
|
"husky": "9.1.7",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
"sst": "3.17.22",
|
"sst": "3.17.23",
|
||||||
"turbo": "2.5.6",
|
"turbo": "2.5.6",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"@solidjs/meta": "^0.29.4",
|
"@solidjs/meta": "^0.29.4",
|
||||||
"@solidjs/router": "^0.15.0",
|
"@solidjs/router": "^0.15.0",
|
||||||
"@solidjs/start": "^1.1.0",
|
"@solidjs/start": "^1.1.0",
|
||||||
|
"chart.js": "4.5.1",
|
||||||
"solid-js": "catalog:",
|
"solid-js": "catalog:",
|
||||||
"vinxi": "^0.5.7",
|
"vinxi": "^0.5.7",
|
||||||
"zod": "catalog:",
|
"zod": "catalog:",
|
||||||
@@ -39,7 +41,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/core": {
|
"packages/console/core": {
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sts": "3.782.0",
|
"@aws-sdk/client-sts": "3.782.0",
|
||||||
"@jsx-email/render": "1.1.1",
|
"@jsx-email/render": "1.1.1",
|
||||||
@@ -66,7 +68,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/function": {
|
"packages/console/function": {
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/anthropic": "2.0.0",
|
"@ai-sdk/anthropic": "2.0.0",
|
||||||
"@ai-sdk/openai": "2.0.2",
|
"@ai-sdk/openai": "2.0.2",
|
||||||
@@ -90,7 +92,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/mail": {
|
"packages/console/mail": {
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
@@ -106,12 +108,15 @@
|
|||||||
"@cloudflare/workers-types": "catalog:",
|
"@cloudflare/workers-types": "catalog:",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@cloudflare/workers-types": "catalog:",
|
||||||
"@tsconfig/node22": "22.0.2",
|
"@tsconfig/node22": "22.0.2",
|
||||||
|
"@types/node": "catalog:",
|
||||||
|
"cloudflare": "5.2.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/desktop": {
|
"packages/desktop": {
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
@@ -151,7 +156,7 @@
|
|||||||
},
|
},
|
||||||
"packages/function": {
|
"packages/function": {
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/auth-app": "8.0.1",
|
"@octokit/auth-app": "8.0.1",
|
||||||
"@octokit/rest": "22.0.0",
|
"@octokit/rest": "22.0.0",
|
||||||
@@ -167,7 +172,7 @@
|
|||||||
},
|
},
|
||||||
"packages/opencode": {
|
"packages/opencode": {
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
@@ -175,6 +180,7 @@
|
|||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"@actions/github": "6.0.1",
|
"@actions/github": "6.0.1",
|
||||||
"@agentclientprotocol/sdk": "0.5.1",
|
"@agentclientprotocol/sdk": "0.5.1",
|
||||||
|
"@ai-sdk/mcp": "0.0.8",
|
||||||
"@clack/prompts": "1.0.0-alpha.1",
|
"@clack/prompts": "1.0.0-alpha.1",
|
||||||
"@hono/standard-validator": "0.1.5",
|
"@hono/standard-validator": "0.1.5",
|
||||||
"@hono/zod-validator": "catalog:",
|
"@hono/zod-validator": "catalog:",
|
||||||
@@ -185,8 +191,8 @@
|
|||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
"@opencode-ai/script": "workspace:*",
|
"@opencode-ai/script": "workspace:*",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@opentui/core": "0.1.36",
|
"@opentui/core": "0.1.47",
|
||||||
"@opentui/solid": "0.1.36",
|
"@opentui/solid": "0.1.47",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@pierre/precision-diffs": "catalog:",
|
"@pierre/precision-diffs": "catalog:",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
@@ -245,7 +251,7 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"zod": "catalog:",
|
"zod": "catalog:",
|
||||||
@@ -265,7 +271,7 @@
|
|||||||
},
|
},
|
||||||
"packages/sdk/js": {
|
"packages/sdk/js": {
|
||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@hey-api/openapi-ts": "0.81.0",
|
"@hey-api/openapi-ts": "0.81.0",
|
||||||
"@tsconfig/node22": "catalog:",
|
"@tsconfig/node22": "catalog:",
|
||||||
@@ -276,7 +282,7 @@
|
|||||||
},
|
},
|
||||||
"packages/slack": {
|
"packages/slack": {
|
||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@slack/bolt": "^3.17.1",
|
"@slack/bolt": "^3.17.1",
|
||||||
@@ -289,7 +295,7 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
@@ -317,9 +323,19 @@
|
|||||||
"vite-plugin-solid": "catalog:",
|
"vite-plugin-solid": "catalog:",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"packages/util": {
|
||||||
|
"name": "@opencode-ai/util",
|
||||||
|
"version": "1.0.85",
|
||||||
|
"dependencies": {
|
||||||
|
"zod": "catalog:",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "catalog:",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/web": {
|
"packages/web": {
|
||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/cloudflare": "12.6.3",
|
"@astrojs/cloudflare": "12.6.3",
|
||||||
"@astrojs/markdown-remark": "6.3.1",
|
"@astrojs/markdown-remark": "6.3.1",
|
||||||
@@ -365,7 +381,7 @@
|
|||||||
"@hono/zod-validator": "0.4.2",
|
"@hono/zod-validator": "0.4.2",
|
||||||
"@kobalte/core": "0.13.11",
|
"@kobalte/core": "0.13.11",
|
||||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||||
"@pierre/precision-diffs": "0.4.2",
|
"@pierre/precision-diffs": "0.4.4",
|
||||||
"@solidjs/meta": "0.29.4",
|
"@solidjs/meta": "0.29.4",
|
||||||
"@tailwindcss/vite": "4.1.11",
|
"@tailwindcss/vite": "4.1.11",
|
||||||
"@tsconfig/bun": "1.0.9",
|
"@tsconfig/bun": "1.0.9",
|
||||||
@@ -373,7 +389,7 @@
|
|||||||
"@types/bun": "1.3.0",
|
"@types/bun": "1.3.0",
|
||||||
"@types/node": "22.13.9",
|
"@types/node": "22.13.9",
|
||||||
"@typescript/native-preview": "7.0.0-dev.20251014.1",
|
"@typescript/native-preview": "7.0.0-dev.20251014.1",
|
||||||
"ai": "5.0.8",
|
"ai": "5.0.97",
|
||||||
"diff": "8.0.2",
|
"diff": "8.0.2",
|
||||||
"fuzzysort": "3.1.0",
|
"fuzzysort": "3.1.0",
|
||||||
"hono": "4.7.10",
|
"hono": "4.7.10",
|
||||||
@@ -408,12 +424,14 @@
|
|||||||
|
|
||||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-uyyaO4KhxoIKZztREqLPh+6/K3ZJx/rp72JKoUEL9/kC+vfQTThUfPnY/bUryUpcnawx8IY/tSoYNOi/8PCv7w=="],
|
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-uyyaO4KhxoIKZztREqLPh+6/K3ZJx/rp72JKoUEL9/kC+vfQTThUfPnY/bUryUpcnawx8IY/tSoYNOi/8PCv7w=="],
|
||||||
|
|
||||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@1.0.4", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-1roLdgMbFU3Nr4MC97/te7w6OqxsWBkDUkpbCcvxF3jz/ku91WVaJldn/PKU8feMKNyI5W9wnqhbjb1BqbExOQ=="],
|
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.12", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W+cB1sOWvPcz9qiIsNtD+HxUrBUva2vWv2K1EFukuImX+HA0uZx3EyyOjhYQ9gtf/teqEG80M6OvJ7xx/VLV2A=="],
|
||||||
|
|
||||||
"@ai-sdk/google": ["@ai-sdk/google@2.0.11", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.7" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-dnVIgSz1DZD/0gVau6ifYN3HZFN15HZwC9VjevTFfvrfSfbEvpXj5x/k/zk/0XuQrlQ5g8JiwJtxc9bx24x2xw=="],
|
"@ai-sdk/google": ["@ai-sdk/google@2.0.11", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.7" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-dnVIgSz1DZD/0gVau6ifYN3HZFN15HZwC9VjevTFfvrfSfbEvpXj5x/k/zk/0XuQrlQ5g8JiwJtxc9bx24x2xw=="],
|
||||||
|
|
||||||
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.16", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.9", "@ai-sdk/google": "2.0.11", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.7", "google-auth-library": "^9.15.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-tStlnOCRGRqKKJSCOtXhijX4r9kYVK2v+Vs7miJnfvr3sZfO8nRS0xnNhfgu17xuNi5LMMufeCYURTz4lKxzUQ=="],
|
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.16", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.9", "@ai-sdk/google": "2.0.11", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.7", "google-auth-library": "^9.15.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-tStlnOCRGRqKKJSCOtXhijX4r9kYVK2v+Vs7miJnfvr3sZfO8nRS0xnNhfgu17xuNi5LMMufeCYURTz4lKxzUQ=="],
|
||||||
|
|
||||||
|
"@ai-sdk/mcp": ["@ai-sdk/mcp@0.0.8", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "pkce-challenge": "^5.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9y9GuGcZ9/+pMIHfpOCJgZVp+AZMv6TkjX2NVT17SQZvTF2N8LXuCXyoUPyi1PxIxzxl0n463LxxaB2O6olC+Q=="],
|
||||||
|
|
||||||
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.2", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-D4zYz2uR90aooKQvX1XnS00Z7PkbrcY+snUvPfm5bCabTG7bzLrVtD56nJ5bSaZG8lmuOMfXpyiEEArYLyWPpw=="],
|
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.2", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-D4zYz2uR90aooKQvX1XnS00Z7PkbrcY+snUvPfm5bCabTG7bzLrVtD56nJ5bSaZG8lmuOMfXpyiEEArYLyWPpw=="],
|
||||||
|
|
||||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-luHVcU+yKzwv3ekKgbP3v+elUVxb2Rt+8c6w9qi7g2NYG2/pEL21oIrnaEnc6UtTZLLZX9EFBcpq2N1FQKDIMw=="],
|
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-luHVcU+yKzwv3ekKgbP3v+elUVxb2Rt+8c6w9qi7g2NYG2/pEL21oIrnaEnc6UtTZLLZX9EFBcpq2N1FQKDIMw=="],
|
||||||
@@ -434,7 +452,7 @@
|
|||||||
|
|
||||||
"@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="],
|
"@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="],
|
||||||
|
|
||||||
"@astrojs/mdx": ["@astrojs/mdx@4.3.9", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.8", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "picocolors": "^1.1.1", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-80LHiM4z3FxAjATHNgFpa8nlTNSprAWB4UUKnr/QG56Pwk7uRnJWrXlok4wSCi/3fg8kTZ98A408Q91M+iqJdw=="],
|
"@astrojs/mdx": ["@astrojs/mdx@4.3.10", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.8", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "picocolors": "^1.1.1", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-2T5+XIr7PMqMeXhRofXY5NlY4lA0Km+wkfsqmr9lq5KXUHpGlKPQ9dlDZJP9E/CtljJyEBNS17zq66LrIJ1tiQ=="],
|
||||||
|
|
||||||
"@astrojs/prism": ["@astrojs/prism@3.2.0", "", { "dependencies": { "prismjs": "^1.29.0" } }, "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw=="],
|
"@astrojs/prism": ["@astrojs/prism@3.2.0", "", { "dependencies": { "prismjs": "^1.29.0" } }, "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw=="],
|
||||||
|
|
||||||
@@ -574,15 +592,15 @@
|
|||||||
|
|
||||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.9", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "^1.20250927.0" }, "optionalPeers": ["workerd"] }, "sha512-Drm7qlTKnvncEv+DANiQNEonq0H0LyIsoFZYJ6tJ8OhAoy5udIE8yp6BsVDYcIjcYLIybp4M7c/P7ly/56SoHg=="],
|
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.9", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "^1.20250927.0" }, "optionalPeers": ["workerd"] }, "sha512-Drm7qlTKnvncEv+DANiQNEonq0H0LyIsoFZYJ6tJ8OhAoy5udIE8yp6BsVDYcIjcYLIybp4M7c/P7ly/56SoHg=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20251011.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-0DirVP+Z82RtZLlK2B+VhLOkk+ShBqDYO/jhcRw4oVlp0TOvk3cOVZChrt3+y3NV8Y/PYgTEywzLKFSziK4wCg=="],
|
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20251105.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-nztUP35wTtUKM+681dBWtUNSySNWELTV+LY43oWy7ZhK19/iBJPQoFY7xpvF7zy4qOOShtise259B65DS4/71Q=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20251011.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1WuFBGwZd15p4xssGN/48OE2oqokIuc51YvHvyNivyV8IYnAs3G9bJNGWth1X7iMDPe4g44pZrKhRnISS2+5dA=="],
|
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20251105.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-WS/dvPYTW/+gs8s0UvDqDY7wcuIAg/hUpjrMNGepr+Mo38vMU39FYhJQOly99oJCXxMluQqAnRKg09b/9Gr+Rg=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20251011.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BccMiBzFlWZyFghIw2szanmYJrJGBGHomw2y/GV6pYXChFzMGZkeCEMfmCyJj29xczZXxcZmUVJxNy4eJxO8QA=="],
|
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20251105.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RdHRHo/hpjR6sNw529FkmslVSz/K3Pb1+i3fIoqUrHCrZOUYzFyz3nLeZh4EYaAhcztLWiSTwBv54bcl4sG3wA=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20251011.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-79o/216lsbAbKEVDZYXR24ivEIE2ysDL9jvo0rDTkViLWju9dAp3CpyetglpJatbSi3uWBPKZBEOqN68zIjVsQ=="],
|
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20251105.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-5zkxQCqLjwrqZVVJh92J2Drv6xifkP8kN2ltjHdwZQlVzfDW48d7tAtCm1ZooUv204ixvZFarusCfL+IRjExZg=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20251011.0", "", { "os": "win32", "cpu": "x64" }, "sha512-RIXUQRchFdqEvaUqn1cXZXSKjpqMaSaVAkI5jNZ8XzAw/bw2bcdOVUtakrflgxDprltjFb0PTNtuss1FKtH9Jg=="],
|
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20251105.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6BpkfjBIbGR+4FBOcZGcWDLM0XQuoI6R9Dublj/BKf4pv0/xJ4zHdnaYUb5NIlC75L55Ouqw0CEJasoKlMjgnw=="],
|
||||||
|
|
||||||
"@cloudflare/workers-types": ["@cloudflare/workers-types@4.20251008.0", "", {}, "sha512-dZLkO4PbCL0qcCSKzuW7KE4GYe49lI12LCfQ5y9XeSwgYBoAUbwH4gmJ6A0qUIURiTJTkGkRkhVPqpq2XNgYRA=="],
|
"@cloudflare/workers-types": ["@cloudflare/workers-types@4.20251008.0", "", {}, "sha512-dZLkO4PbCL0qcCSKzuW7KE4GYe49lI12LCfQ5y9XeSwgYBoAUbwH4gmJ6A0qUIURiTJTkGkRkhVPqpq2XNgYRA=="],
|
||||||
|
|
||||||
@@ -866,6 +884,8 @@
|
|||||||
|
|
||||||
"@kobalte/utils": ["@kobalte/utils@0.9.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w=="],
|
"@kobalte/utils": ["@kobalte/utils@0.9.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w=="],
|
||||||
|
|
||||||
|
"@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="],
|
||||||
|
|
||||||
"@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg=="],
|
"@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg=="],
|
||||||
|
|
||||||
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
|
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
|
||||||
@@ -958,25 +978,27 @@
|
|||||||
|
|
||||||
"@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"],
|
"@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"],
|
||||||
|
|
||||||
|
"@opencode-ai/util": ["@opencode-ai/util@workspace:packages/util"],
|
||||||
|
|
||||||
"@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
|
"@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
|
||||||
|
|
||||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||||
|
|
||||||
"@opentui/core": ["@opentui/core@0.1.36", "", { "dependencies": { "bun-ffi-structs": "^0.1.0", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.36", "@opentui/core-darwin-x64": "0.1.36", "@opentui/core-linux-arm64": "0.1.36", "@opentui/core-linux-x64": "0.1.36", "@opentui/core-win32-arm64": "0.1.36", "@opentui/core-win32-x64": "0.1.36", "bun-webgpu": "0.1.3", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-urDrj33udJ0dJGkZv+T5U0mCFBOOvUt9Tvqkrj8aRvi6kN0Bc5d2COuWcpAKo0TO9/PvjSwHC+CMnw2Sr46/ug=="],
|
"@opentui/core": ["@opentui/core@0.1.47", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.47", "@opentui/core-darwin-x64": "0.1.47", "@opentui/core-linux-arm64": "0.1.47", "@opentui/core-linux-x64": "0.1.47", "@opentui/core-win32-arm64": "0.1.47", "@opentui/core-win32-x64": "0.1.47", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-gKcYX9EJ/e5VLEwBH2kalDr5xoI9MEanzQV7uV3Sb2Z9+ndwEUShKKna3odN8g4E20c4sX2VpwmB9hhl3Tsd9w=="],
|
||||||
|
|
||||||
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.36", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/fb0k1H0CeTroVt2UoEAcVrEx1cIYy4B2zfX0MrwUkIfXi36aoIBnisBeYvyCpsQfxFAkyLYCCA3NzaYEyC5hg=="],
|
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.47", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0/u4VkJJPvW24cZzMaKf6Dm+VzeO1a94l6NV3AQ1Wb+pPTEyOmNWkRvj03ZrRLMCyQduaFVtlnor8DVCk6OHuQ=="],
|
||||||
|
|
||||||
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.36", "", { "os": "darwin", "cpu": "x64" }, "sha512-PZMydJbSDUoEWqZsyEV8+FSwMT+r7mWFL0ABgdALI3AOrSr7Z8dMcRnFWl8LhriuHS589THvETJEN28L4q/E2Q=="],
|
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.47", "", { "os": "darwin", "cpu": "x64" }, "sha512-y1+c/e+IaZAj5N02GnD+oaubbb5JiW5eKgF0h58kw73iXDMfynuoGOpREz58i1rUFYOMYJGdrSjEHtXk2pD2XA=="],
|
||||||
|
|
||||||
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.36", "", { "os": "linux", "cpu": "arm64" }, "sha512-ATR+vdtraZEC/gHR1mQa/NYPlqFNBpsnnJAGepQmcxm85VceLYM701QaaIgNAwyYXiP6RQN1ZCv06MD1Ph1m4w=="],
|
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.47", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZESHmqILtfb6FFEfi40JGKl8z0+LhOSoHgfOK1PPyuyRT9Mk8uXeQgPMF5W6Ac0pp4w+uWVC4TrFjijCCSiaUQ=="],
|
||||||
|
|
||||||
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.36", "", { "os": "linux", "cpu": "x64" }, "sha512-INsnPtcZVx68C+0Vd0L9+akDwNbWblUDqLmY9CftfmeLFubzvJXNRYTBvr7lX68fcst6Ho+0beUxyUoClKc0rg=="],
|
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.47", "", { "os": "linux", "cpu": "x64" }, "sha512-qfvy1qshgnZMcAHQ3MS093IBjxM2pPx+kEnW7icsyud60zoJgoUugdN2kjgJiIJiYX3f3PgE68J6CVW2MCtYfQ=="],
|
||||||
|
|
||||||
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.36", "", { "os": "win32", "cpu": "arm64" }, "sha512-x9lDZTL+xE8jsG1hP4pdsqCsZBu77JNR/ze5F7ZQkYQEC6Zl/XJtL1YT08nUlWOu4NMSws2xXV0lS/sJkbEgPA=="],
|
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.47", "", { "os": "win32", "cpu": "arm64" }, "sha512-f6OoPnaz303H6fudi8blS+iEcJtlFlcqdBoWnWnJQfN9rLmajW3Yf7RfpNOoLUlDcwxQLyTL/5EHwbcG8D4r7A=="],
|
||||||
|
|
||||||
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.36", "", { "os": "win32", "cpu": "x64" }, "sha512-WVU+qtAfJe8ikPWbw8Hfli15GuQTMKiceTkF5lql5AQYy7PKYtGTzWszxOZKeUU1/eEd2X4REi8Bn0TprEMxYw=="],
|
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.47", "", { "os": "win32", "cpu": "x64" }, "sha512-lQnJg7FucyyTbN/ybTj5FZ7S8OAfT5KxXDR5l9Sla7R5MIDY6nBXYM3GWeF81jzDd4K4Z/0hxNFtWSopEXRFYg=="],
|
||||||
|
|
||||||
"@opentui/solid": ["@opentui/solid@0.1.36", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.36", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-oHI01kZgyNecvXRFyQKJEDC5TCcsvfTPxHCa/XjbcZzH2qE2rfYMUF0mpwlLqoY9b3pm3w7Tpa8upzi1euBGJg=="],
|
"@opentui/solid": ["@opentui/solid@0.1.47", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.47", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-azN2sf8X/6HiLkz8ip2lcY532ApNEkl+BHd+wml/HdwdgLE7nthgA6x8Pgvi7f4qkRmpeYATU+danIzB6K6B8A=="],
|
||||||
|
|
||||||
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
|
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
|
||||||
|
|
||||||
@@ -1034,7 +1056,7 @@
|
|||||||
|
|
||||||
"@petamoriken/float16": ["@petamoriken/float16@3.9.3", "", {}, "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g=="],
|
"@petamoriken/float16": ["@petamoriken/float16@3.9.3", "", {}, "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g=="],
|
||||||
|
|
||||||
"@pierre/precision-diffs": ["@pierre/precision-diffs@0.4.2", "", { "dependencies": { "@shikijs/core": "3.14.0", "@shikijs/transformers": "3.14.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.14.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-C6LbruH24BCp4awI47D5iMtVaZZD6GkzqBoDw+Sfu7DB3hC9y/rZr1C2BD7AUzAKwByTfFnh16Zp11ipfPqLKw=="],
|
"@pierre/precision-diffs": ["@pierre/precision-diffs@0.4.4", "", { "dependencies": { "@shikijs/core": "3.14.0", "@shikijs/transformers": "3.14.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.14.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-9bhWs+hsz1i0/SMIrzce+fFrSec8aLIFrJYTGHATlynmQovngIWz1Gc+XwGigvY4+zSMksrGPzO5HiaNlvRqtQ=="],
|
||||||
|
|
||||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||||
|
|
||||||
@@ -1126,49 +1148,49 @@
|
|||||||
|
|
||||||
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
|
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.2", "", { "os": "android", "cpu": "arm" }, "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="],
|
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.2", "", { "os": "android", "cpu": "arm64" }, "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="],
|
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="],
|
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="],
|
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="],
|
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="],
|
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.2", "", { "os": "linux", "cpu": "arm" }, "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="],
|
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="],
|
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="],
|
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="],
|
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.2", "", { "os": "linux", "cpu": "none" }, "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="],
|
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="],
|
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.2", "", { "os": "linux", "cpu": "none" }, "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="],
|
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.2", "", { "os": "linux", "cpu": "none" }, "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="],
|
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="],
|
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.2", "", { "os": "linux", "cpu": "x64" }, "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="],
|
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA=="],
|
||||||
|
|
||||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="],
|
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.2", "", { "os": "none", "cpu": "arm64" }, "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="],
|
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="],
|
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="],
|
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.2", "", { "os": "win32", "cpu": "x64" }, "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
|
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.2", "", { "os": "win32", "cpu": "x64" }, "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA=="],
|
||||||
|
|
||||||
"@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="],
|
"@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="],
|
||||||
|
|
||||||
@@ -1204,57 +1226,57 @@
|
|||||||
|
|
||||||
"@slack/web-api": ["@slack/web-api@6.13.0", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.11.0", "@types/is-stream": "^1.1.0", "@types/node": ">=12.0.0", "axios": "^1.7.4", "eventemitter3": "^3.1.0", "form-data": "^2.5.0", "is-electron": "2.2.2", "is-stream": "^1.1.0", "p-queue": "^6.6.1", "p-retry": "^4.0.0" } }, "sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g=="],
|
"@slack/web-api": ["@slack/web-api@6.13.0", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.11.0", "@types/is-stream": "^1.1.0", "@types/node": ">=12.0.0", "axios": "^1.7.4", "eventemitter3": "^3.1.0", "form-data": "^2.5.0", "is-electron": "2.2.2", "is-stream": "^1.1.0", "p-queue": "^6.6.1", "p-retry": "^4.0.0" } }, "sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g=="],
|
||||||
|
|
||||||
"@smithy/abort-controller": ["@smithy/abort-controller@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-Z4DUr/AkgyFf1bOThW2HwzREagee0sB5ycl+hDiSZOfRLW8ZgrOjDi6g8mHH19yyU5E2A/64W3z6SMIf5XiUSQ=="],
|
"@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="],
|
||||||
|
|
||||||
"@smithy/config-resolver": ["@smithy/config-resolver@4.4.2", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.4", "@smithy/types": "^4.8.1", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.4", "@smithy/util-middleware": "^4.2.4", "tslib": "^2.6.2" } }, "sha512-4Jys0ni2tB2VZzgslbEgszZyMdTkPOFGA8g+So/NjR8oy6Qwaq4eSwsrRI+NMtb0Dq4kqCzGUu/nGUx7OM/xfw=="],
|
"@smithy/config-resolver": ["@smithy/config-resolver@4.4.3", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw=="],
|
||||||
|
|
||||||
"@smithy/core": ["@smithy/core@3.17.2", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.4", "@smithy/protocol-http": "^5.3.4", "@smithy/types": "^4.8.1", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.4", "@smithy/util-stream": "^4.5.5", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-n3g4Nl1Te+qGPDbNFAYf+smkRVB+JhFsGy9uJXXZQEufoP4u0r+WLh6KvTDolCswaagysDc/afS1yvb2jnj1gQ=="],
|
"@smithy/core": ["@smithy/core@3.18.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-vGSDXOJFZgOPTatSI1ly7Gwyy/d/R9zh2TO3y0JZ0uut5qQ88p9IaWaZYIWSSqtdekNM4CGok/JppxbAff4KcQ=="],
|
||||||
|
|
||||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.4", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.4", "@smithy/property-provider": "^4.2.4", "@smithy/types": "^4.8.1", "@smithy/url-parser": "^4.2.4", "tslib": "^2.6.2" } }, "sha512-YVNMjhdz2pVto5bRdux7GMs0x1m0Afz3OcQy/4Yf9DH4fWOtroGH7uLvs7ZmDyoBJzLdegtIPpXrpJOZWvUXdw=="],
|
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ=="],
|
||||||
|
|
||||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.4", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.8.1", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-aV8blR9RBDKrOlZVgjOdmOibTC2sBXNiT7WA558b4MPdsLTV6sbyc1WIE9QiIuYMJjYtnPLciefoqSW8Gi+MZQ=="],
|
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.5", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA=="],
|
||||||
|
|
||||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.4", "@smithy/querystring-builder": "^4.2.4", "@smithy/types": "^4.8.1", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-mg83SM3FLI8Sa2ooTJbsh5MFfyMTyNRwxqpKHmE0ICRIa66Aodv80DMsTQI02xBLVJ0hckwqTRr5IGAbbWuFLQ=="],
|
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="],
|
||||||
|
|
||||||
"@smithy/hash-node": ["@smithy/hash-node@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kKU0gVhx/ppVMntvUOZE7WRMFW86HuaxLwvqileBEjL7PoILI8/djoILw3gPQloGVE6O0oOzqafxeNi2KbnUJw=="],
|
"@smithy/hash-node": ["@smithy/hash-node@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA=="],
|
||||||
|
|
||||||
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-z6aDLGiHzsMhbS2MjetlIWopWz//K+mCoPXjW6aLr0mypF+Y7qdEh5TyJ20Onf9FbWHiWl4eC+rITdizpnXqOw=="],
|
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A=="],
|
||||||
|
|
||||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="],
|
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="],
|
||||||
|
|
||||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.4", "", { "dependencies": { "@smithy/protocol-http": "^5.3.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-hJRZuFS9UsElX4DJSJfoX4M1qXRH+VFiLMUnhsWvtOOUWRNvvOfDaUSdlNbjwv1IkpVjj/Rd/O59Jl3nhAcxow=="],
|
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A=="],
|
||||||
|
|
||||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.6", "", { "dependencies": { "@smithy/core": "^3.17.2", "@smithy/middleware-serde": "^4.2.4", "@smithy/node-config-provider": "^4.3.4", "@smithy/shared-ini-file-loader": "^4.3.4", "@smithy/types": "^4.8.1", "@smithy/url-parser": "^4.2.4", "@smithy/util-middleware": "^4.2.4", "tslib": "^2.6.2" } }, "sha512-PXehXofGMFpDqr933rxD8RGOcZ0QBAWtuzTgYRAHAL2BnKawHDEdf/TnGpcmfPJGwonhginaaeJIKluEojiF/w=="],
|
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.7", "", { "dependencies": { "@smithy/core": "^3.18.0", "@smithy/middleware-serde": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-i8Mi8OuY6Yi82Foe3iu7/yhBj1HBRoOQwBSsUNYglJTNSFaWYTNM2NauBBs/7pq2sqkLRqeUXA3Ogi2utzpUlQ=="],
|
||||||
|
|
||||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.4", "@smithy/protocol-http": "^5.3.4", "@smithy/service-error-classification": "^4.2.4", "@smithy/smithy-client": "^4.9.2", "@smithy/types": "^4.8.1", "@smithy/util-middleware": "^4.2.4", "@smithy/util-retry": "^4.2.4", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-OhLx131znrEDxZPAvH/OYufR9d1nB2CQADyYFN4C3V/NQS7Mg4V6uvxHC/Dr96ZQW8IlHJTJ+vAhKt6oxWRndA=="],
|
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/protocol-http": "^5.3.5", "@smithy/service-error-classification": "^4.2.5", "@smithy/smithy-client": "^4.9.3", "@smithy/types": "^4.9.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-E7Vc6WHCHlzDRTx1W0jZ6J1L6ziEV0PIWcUdmfL4y+c8r7WYr6I+LkQudaD8Nfb7C5c4P3SQ972OmXHtv6m/OA=="],
|
||||||
|
|
||||||
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.4", "", { "dependencies": { "@smithy/protocol-http": "^5.3.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-jUr3x2CDhV15TOX2/Uoz4gfgeqLrRoTQbYAuhLS7lcVKNev7FeYSJ1ebEfjk+l9kbb7k7LfzIR/irgxys5ZTOg=="],
|
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-La1ldWTJTZ5NqQyPqnCNeH9B+zjFhrNoQIL1jTh4zuqXRlmXhxYHhMtI1/92OlnoAtp6JoN7kzuwhWoXrBwPqg=="],
|
||||||
|
|
||||||
"@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-Gy3TKCOnm9JwpFooldwAboazw+EFYlC+Bb+1QBsSi5xI0W5lX81j/P5+CXvD/9ZjtYKRgxq+kkqd/KOHflzvgA=="],
|
"@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ=="],
|
||||||
|
|
||||||
"@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.4", "", { "dependencies": { "@smithy/property-provider": "^4.2.4", "@smithy/shared-ini-file-loader": "^4.3.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-3X3w7qzmo4XNNdPKNS4nbJcGSwiEMsNsRSunMA92S4DJLLIrH5g1AyuOA2XKM9PAPi8mIWfqC+fnfKNsI4KvHw=="],
|
"@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg=="],
|
||||||
|
|
||||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.4", "", { "dependencies": { "@smithy/abort-controller": "^4.2.4", "@smithy/protocol-http": "^5.3.4", "@smithy/querystring-builder": "^4.2.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-VXHGfzCXLZeKnFp6QXjAdy+U8JF9etfpUXD1FAbzY1GzsFJiDQRQIt2CnMUvUdz3/YaHNqT3RphVWMUpXTIODA=="],
|
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="],
|
||||||
|
|
||||||
"@smithy/property-provider": ["@smithy/property-provider@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-g2DHo08IhxV5GdY3Cpt/jr0mkTlAD39EJKN27Jb5N8Fb5qt8KG39wVKTXiTRCmHHou7lbXR8nKVU14/aRUf86w=="],
|
"@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="],
|
||||||
|
|
||||||
"@smithy/protocol-http": ["@smithy/protocol-http@5.3.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw=="],
|
"@smithy/protocol-http": ["@smithy/protocol-http@5.3.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ=="],
|
||||||
|
|
||||||
"@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-KQ1gFXXC+WsbPFnk7pzskzOpn4s+KheWgO3dzkIEmnb6NskAIGp/dGdbKisTPJdtov28qNDohQrgDUKzXZBLig=="],
|
"@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="],
|
||||||
|
|
||||||
"@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-aHb5cqXZocdzEkZ/CvhVjdw5l4r1aU/9iMEyoKzH4eXMowT6M0YjBpp7W/+XjkBnY8Xh0kVd55GKjnPKlCwinQ=="],
|
"@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ=="],
|
||||||
|
|
||||||
"@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1" } }, "sha512-fdWuhEx4+jHLGeew9/IvqVU/fxT/ot70tpRGuOLxE3HzZOyKeTQfYeV1oaBXpzi93WOk668hjMuuagJ2/Qs7ng=="],
|
"@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="],
|
||||||
|
|
||||||
"@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.3.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-y5ozxeQ9omVjbnJo9dtTsdXj9BEvGx2X8xvRgKnV+/7wLBuYJQL6dOa/qMY6omyHi7yjt1OA97jZLoVRYi8lxA=="],
|
"@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="],
|
||||||
|
|
||||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.3.4", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.4", "@smithy/types": "^4.8.1", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.4", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ScDCpasxH7w1HXHYbtk3jcivjvdA1VICyAdgvVqKhKKwxi+MTwZEqFw0minE+oZ7F07oF25xh4FGJxgqgShz0A=="],
|
"@smithy/signature-v4": ["@smithy/signature-v4@5.3.5", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w=="],
|
||||||
|
|
||||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.9.2", "", { "dependencies": { "@smithy/core": "^3.17.2", "@smithy/middleware-endpoint": "^4.3.6", "@smithy/middleware-stack": "^4.2.4", "@smithy/protocol-http": "^5.3.4", "@smithy/types": "^4.8.1", "@smithy/util-stream": "^4.5.5", "tslib": "^2.6.2" } }, "sha512-gZU4uAFcdrSi3io8U99Qs/FvVdRxPvIMToi+MFfsy/DN9UqtknJ1ais+2M9yR8e0ASQpNmFYEKeIKVcMjQg3rg=="],
|
"@smithy/smithy-client": ["@smithy/smithy-client@4.9.3", "", { "dependencies": { "@smithy/core": "^3.18.0", "@smithy/middleware-endpoint": "^4.3.7", "@smithy/middleware-stack": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-8tlueuTgV5n7inQCkhyptrB3jo2AO80uGrps/XTYZivv5MFQKKBj3CIWIGMI2fRY5LEduIiazOhAWdFknY1O9w=="],
|
||||||
|
|
||||||
"@smithy/types": ["@smithy/types@4.8.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-N0Zn0OT1zc+NA+UVfkYqQzviRh5ucWwO7mBV3TmHHprMnfcJNfhlPicDkBHi0ewbh+y3evR6cNAW0Raxvb01NA=="],
|
"@smithy/types": ["@smithy/types@4.9.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA=="],
|
||||||
|
|
||||||
"@smithy/url-parser": ["@smithy/url-parser@4.2.4", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-w/N/Iw0/PTwJ36PDqU9PzAwVElo4qXxCC0eCTlUtIz/Z5V/2j/cViMHi0hPukSBHp4DVwvUlUhLgCzqSJ6plrg=="],
|
"@smithy/url-parser": ["@smithy/url-parser@4.2.5", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ=="],
|
||||||
|
|
||||||
"@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="],
|
"@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="],
|
||||||
|
|
||||||
@@ -1266,19 +1288,19 @@
|
|||||||
|
|
||||||
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="],
|
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="],
|
||||||
|
|
||||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.4", "@smithy/smithy-client": "^4.9.2", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-GwaGjv/QLuL/QHQaqhf/maM7+MnRFQQs7Bsl6FlaeK6lm6U7mV5AAnVabw68cIoMl5FQFyKK62u7RWRzWL25OQ=="],
|
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.6", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.3", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-kbpuXbEf2YQ9zEE6eeVnUCQWO0e1BjMnKrXL8rfXgiWA0m8/E0leU4oSNzxP04WfCmW8vjEqaDeXWxwE4tpOjQ=="],
|
||||||
|
|
||||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.8", "", { "dependencies": { "@smithy/config-resolver": "^4.4.2", "@smithy/credential-provider-imds": "^4.2.4", "@smithy/node-config-provider": "^4.3.4", "@smithy/property-provider": "^4.2.4", "@smithy/smithy-client": "^4.9.2", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-gIoTf9V/nFSIZ0TtgDNLd+Ws59AJvijmMDYrOozoMHPJaG9cMRdqNO50jZTlbM6ydzQYY8L/mQ4tKSw/TB+s6g=="],
|
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.9", "", { "dependencies": { "@smithy/config-resolver": "^4.4.3", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.3", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-dgyribrVWN5qE5usYJ0m5M93mVM3L3TyBPZWe1Xl6uZlH2gzfQx3dz+ZCdW93lWqdedJRkOecnvbnoEEXRZ5VQ=="],
|
||||||
|
|
||||||
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.4", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-f+nBDhgYRCmUEDKEQb6q0aCcOTXRDqH5wWaFHJxt4anB4pKHlgGoYP3xtioKXH64e37ANUkzWf6p4Mnv1M5/Vg=="],
|
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A=="],
|
||||||
|
|
||||||
"@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="],
|
"@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="],
|
||||||
|
|
||||||
"@smithy/util-middleware": ["@smithy/util-middleware@4.2.4", "", { "dependencies": { "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-fKGQAPAn8sgV0plRikRVo6g6aR0KyKvgzNrPuM74RZKy/wWVzx3BMk+ZWEueyN3L5v5EDg+P582mKU+sH5OAsg=="],
|
"@smithy/util-middleware": ["@smithy/util-middleware@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA=="],
|
||||||
|
|
||||||
"@smithy/util-retry": ["@smithy/util-retry@4.2.4", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.4", "@smithy/types": "^4.8.1", "tslib": "^2.6.2" } }, "sha512-yQncJmj4dtv/isTXxRb4AamZHy4QFr4ew8GxS6XLWt7sCIxkPxPzINWd7WLISEFPsIan14zrKgvyAF+/yzfwoA=="],
|
"@smithy/util-retry": ["@smithy/util-retry@4.2.5", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg=="],
|
||||||
|
|
||||||
"@smithy/util-stream": ["@smithy/util-stream@4.5.5", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.5", "@smithy/node-http-handler": "^4.4.4", "@smithy/types": "^4.8.1", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7M5aVFjT+HPilPOKbOmQfCIPchZe4DSBc1wf1+NvHvSoFTiFtauZzT+onZvCj70xhXd0AEmYnZYmdJIuwxOo4w=="],
|
"@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="],
|
||||||
|
|
||||||
"@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="],
|
"@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="],
|
||||||
|
|
||||||
@@ -1318,7 +1340,7 @@
|
|||||||
|
|
||||||
"@solidjs/meta": ["@solidjs/meta@0.29.4", "", { "peerDependencies": { "solid-js": ">=1.8.4" } }, "sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g=="],
|
"@solidjs/meta": ["@solidjs/meta@0.29.4", "", { "peerDependencies": { "solid-js": ">=1.8.4" } }, "sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g=="],
|
||||||
|
|
||||||
"@solidjs/router": ["@solidjs/router@0.15.3", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw=="],
|
"@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="],
|
||||||
|
|
||||||
"@solidjs/start": ["@solidjs/start@1.2.0", "", { "dependencies": { "@tanstack/server-functions-plugin": "1.121.21", "@vinxi/plugin-directives": "^0.5.0", "@vinxi/server-components": "^0.5.0", "cookie-es": "^2.0.0", "defu": "^6.1.2", "error-stack-parser": "^2.1.4", "html-to-image": "^1.11.11", "radix3": "^1.1.0", "seroval": "^1.0.2", "seroval-plugins": "^1.0.2", "shiki": "^1.26.1", "source-map-js": "^1.0.2", "terracotta": "^1.0.4", "tinyglobby": "^0.2.2", "vite-plugin-solid": "^2.11.1" }, "peerDependencies": { "vinxi": "^0.5.7" } }, "sha512-SRv1g3R+4sxZnxCBPK1IedtLKsPhPJ7W/Yv4xEHjM4jJGPWi3ed35/yd0D5zhRK0C7zJIkZKbhnR/S3g8JUD5w=="],
|
"@solidjs/start": ["@solidjs/start@1.2.0", "", { "dependencies": { "@tanstack/server-functions-plugin": "1.121.21", "@vinxi/plugin-directives": "^0.5.0", "@vinxi/server-components": "^0.5.0", "cookie-es": "^2.0.0", "defu": "^6.1.2", "error-stack-parser": "^2.1.4", "html-to-image": "^1.11.11", "radix3": "^1.1.0", "seroval": "^1.0.2", "seroval-plugins": "^1.0.2", "shiki": "^1.26.1", "source-map-js": "^1.0.2", "terracotta": "^1.0.4", "tinyglobby": "^0.2.2", "vite-plugin-solid": "^2.11.1" }, "peerDependencies": { "vinxi": "^0.5.7" } }, "sha512-SRv1g3R+4sxZnxCBPK1IedtLKsPhPJ7W/Yv4xEHjM4jJGPWi3ed35/yd0D5zhRK0C7zJIkZKbhnR/S3g8JUD5w=="],
|
||||||
|
|
||||||
@@ -1432,6 +1454,8 @@
|
|||||||
|
|
||||||
"@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="],
|
"@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="],
|
||||||
|
|
||||||
|
"@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="],
|
||||||
|
|
||||||
"@types/promise.allsettled": ["@types/promise.allsettled@1.0.6", "", {}, "sha512-wA0UT0HeT2fGHzIFV9kWpYz5mdoyLxKrTgMdZQM++5h6pYAFH73HXcQhefg24nD1yivUFEn5KU+EF4b+CXJ4Wg=="],
|
"@types/promise.allsettled": ["@types/promise.allsettled@1.0.6", "", {}, "sha512-wA0UT0HeT2fGHzIFV9kWpYz5mdoyLxKrTgMdZQM++5h6pYAFH73HXcQhefg24nD1yivUFEn5KU+EF4b+CXJ4Wg=="],
|
||||||
|
|
||||||
"@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
|
"@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
|
||||||
@@ -1450,7 +1474,7 @@
|
|||||||
|
|
||||||
"@types/scheduler": ["@types/scheduler@0.26.0", "", {}, "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA=="],
|
"@types/scheduler": ["@types/scheduler@0.26.0", "", {}, "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA=="],
|
||||||
|
|
||||||
"@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="],
|
"@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
|
||||||
|
|
||||||
"@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="],
|
"@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="],
|
||||||
|
|
||||||
@@ -1486,6 +1510,8 @@
|
|||||||
|
|
||||||
"@vercel/nft": ["@vercel/nft@0.30.3", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^10.4.5", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-UEq+eF0ocEf9WQCV1gktxKhha36KDs7jln5qii6UpPf5clMqDc0p3E7d9l2Smx0i9Pm1qpq4S4lLfNl97bbv6w=="],
|
"@vercel/nft": ["@vercel/nft@0.30.3", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^10.4.5", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-UEq+eF0ocEf9WQCV1gktxKhha36KDs7jln5qii6UpPf5clMqDc0p3E7d9l2Smx0i9Pm1qpq4S4lLfNl97bbv6w=="],
|
||||||
|
|
||||||
|
"@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
|
||||||
|
|
||||||
"@vinxi/listhen": ["@vinxi/listhen@1.5.6", "", { "dependencies": { "@parcel/watcher": "^2.3.0", "@parcel/watcher-wasm": "2.3.0", "citty": "^0.1.5", "clipboardy": "^4.0.0", "consola": "^3.2.3", "defu": "^6.1.4", "get-port-please": "^3.1.2", "h3": "^1.10.0", "http-shutdown": "^1.2.2", "jiti": "^1.21.0", "mlly": "^1.5.0", "node-forge": "^1.3.1", "pathe": "^1.1.2", "std-env": "^3.7.0", "ufo": "^1.3.2", "untun": "^0.1.3", "uqr": "^0.1.2" }, "bin": { "listen": "bin/listhen.mjs", "listhen": "bin/listhen.mjs" } }, "sha512-WSN1z931BtasZJlgPp704zJFnQFRg7yzSjkm3MzAWQYe4uXFXlFr1hc5Ac2zae5/HDOz5x1/zDM5Cb54vTCnWw=="],
|
"@vinxi/listhen": ["@vinxi/listhen@1.5.6", "", { "dependencies": { "@parcel/watcher": "^2.3.0", "@parcel/watcher-wasm": "2.3.0", "citty": "^0.1.5", "clipboardy": "^4.0.0", "consola": "^3.2.3", "defu": "^6.1.4", "get-port-please": "^3.1.2", "h3": "^1.10.0", "http-shutdown": "^1.2.2", "jiti": "^1.21.0", "mlly": "^1.5.0", "node-forge": "^1.3.1", "pathe": "^1.1.2", "std-env": "^3.7.0", "ufo": "^1.3.2", "untun": "^0.1.3", "uqr": "^0.1.2" }, "bin": { "listen": "bin/listhen.mjs", "listhen": "bin/listhen.mjs" } }, "sha512-WSN1z931BtasZJlgPp704zJFnQFRg7yzSjkm3MzAWQYe4uXFXlFr1hc5Ac2zae5/HDOz5x1/zDM5Cb54vTCnWw=="],
|
||||||
|
|
||||||
"@vinxi/plugin-directives": ["@vinxi/plugin-directives@0.5.1", "", { "dependencies": { "@babel/parser": "^7.23.5", "acorn": "^8.10.0", "acorn-jsx": "^5.3.2", "acorn-loose": "^8.3.0", "acorn-typescript": "^1.4.3", "astring": "^1.8.6", "magicast": "^0.2.10", "recast": "^0.23.4", "tslib": "^2.6.2" }, "peerDependencies": { "vinxi": "^0.5.5" } }, "sha512-pH/KIVBvBt7z7cXrUH/9uaqcdxjegFC7+zvkZkdOyWzs+kQD5KPf3cl8kC+5ayzXHT+OMlhGhyitytqN3cGmHg=="],
|
"@vinxi/plugin-directives": ["@vinxi/plugin-directives@0.5.1", "", { "dependencies": { "@babel/parser": "^7.23.5", "acorn": "^8.10.0", "acorn-jsx": "^5.3.2", "acorn-loose": "^8.3.0", "acorn-typescript": "^1.4.3", "astring": "^1.8.6", "magicast": "^0.2.10", "recast": "^0.23.4", "tslib": "^2.6.2" }, "peerDependencies": { "vinxi": "^0.5.5" } }, "sha512-pH/KIVBvBt7z7cXrUH/9uaqcdxjegFC7+zvkZkdOyWzs+kQD5KPf3cl8kC+5ayzXHT+OMlhGhyitytqN3cGmHg=="],
|
||||||
@@ -1518,7 +1544,9 @@
|
|||||||
|
|
||||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||||
|
|
||||||
"ai": ["ai@5.0.8", "", { "dependencies": { "@ai-sdk/gateway": "1.0.4", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.1", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-qbnhj046UvG30V1S5WhjBn+RBGEAmi8PSZWqMhRsE3EPxvO5BcePXTZFA23e9MYyWS9zr4Vm8Mv3wQXwLmtIBw=="],
|
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||||
|
|
||||||
|
"ai": ["ai@5.0.97", "", { "dependencies": { "@ai-sdk/gateway": "2.0.12", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8zBx0b/owis4eJI2tAlV8a1Rv0BANmLxontcAelkLNwEHhgfgXeKpDkhNB6OgV+BJSwboIUDkgd9312DdJnCOQ=="],
|
||||||
|
|
||||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||||
|
|
||||||
@@ -1580,7 +1608,7 @@
|
|||||||
|
|
||||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||||
|
|
||||||
"autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],
|
"autoprefixer": ["autoprefixer@10.4.22", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-lite": "^1.0.30001754", "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg=="],
|
||||||
|
|
||||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||||
|
|
||||||
@@ -1610,9 +1638,9 @@
|
|||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"bare-events": ["bare-events@2.8.1", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ=="],
|
"bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="],
|
||||||
|
|
||||||
"bare-fs": ["bare-fs@4.5.0", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-GljgCjeupKZJNetTqxKaQArLK10vpmK28or0+RwWjEl5Rk+/xG3wkpmkv+WrcBm3q1BwHKlnhXzR8O37kcvkXQ=="],
|
"bare-fs": ["bare-fs@4.5.1", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-zGUCsm3yv/ePt2PHNbVxjjn0nNB1MkIaR4wOCxJ2ig5pCf5cCVAYJXVhQg/3OhhJV6DB1ts7Hv0oUaElc2TPQg=="],
|
||||||
|
|
||||||
"bare-os": ["bare-os@3.6.2", "", {}, "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A=="],
|
"bare-os": ["bare-os@3.6.2", "", {}, "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A=="],
|
||||||
|
|
||||||
@@ -1662,7 +1690,7 @@
|
|||||||
|
|
||||||
"brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="],
|
"brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="],
|
||||||
|
|
||||||
"browserslist": ["browserslist@4.27.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", "electron-to-chromium": "^1.5.238", "node-releases": "^2.0.26", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw=="],
|
"browserslist": ["browserslist@4.28.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", "electron-to-chromium": "^1.5.249", "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ=="],
|
||||||
|
|
||||||
"buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
|
"buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
|
||||||
|
|
||||||
@@ -1672,19 +1700,19 @@
|
|||||||
|
|
||||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||||
|
|
||||||
"bun-ffi-structs": ["bun-ffi-structs@0.1.0", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-NoRfJ81pgLIHCzw624/2GS2FuxcU0G4SRJww/4PXvheNVUPSIUjkOC6v1/8rk66tJVCb9oR0D6rDNKK0qT5O2Q=="],
|
"bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
|
"bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
|
||||||
|
|
||||||
"bun-webgpu": ["bun-webgpu@0.1.3", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.3", "bun-webgpu-darwin-x64": "^0.1.3", "bun-webgpu-linux-x64": "^0.1.3", "bun-webgpu-win32-x64": "^0.1.3" } }, "sha512-IXFxaIi4rgsEEpl9n/QVDm5RajCK/0FcOXZeMb52YRjoiAR1YVYK5hLrXT8cm+KDi6LVahA9GJFqOR4yiloVCw=="],
|
"bun-webgpu": ["bun-webgpu@0.1.4", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.4", "bun-webgpu-darwin-x64": "^0.1.4", "bun-webgpu-linux-x64": "^0.1.4", "bun-webgpu-win32-x64": "^0.1.4" } }, "sha512-Kw+HoXl1PMWJTh9wvh63SSRofTA8vYBFCw0XEP1V1fFdQEDhI8Sgf73sdndE/oDpN/7CMx0Yv/q8FCvO39ROMQ=="],
|
||||||
|
|
||||||
"bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-KkNQ9gT7dxGDndQaHTTHss9miukqpczML3pO2nZJoT/nITwe9lw3ZGFJMujkW41BUQ1mDYKFgo5nBGf9xYHPAg=="],
|
"bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eDgLN9teKTfmvrCqgwwmWNsNszxYs7IZdCqk0S1DCarvMhr4wcajoSBlA/nQA0/owwLduPTS8xxCnQp4/N/gDg=="],
|
||||||
|
|
||||||
"bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-TODWnMUbCoqD/wqzlB3oGOBIUWIFly0lqMeBFz/MBV+ndjbnkNrP9huaZJCTkCVEPKGtd1FCM3ExZUtBbnGziA=="],
|
"bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-X+PjwJUWenUmdQBP8EtdItMyieQ6Nlpn+BH518oaouDiSnWj5+b0Y7DNDZJq7Ezom4EaxmqL/uGYZK3aCQ7CXg=="],
|
||||||
|
|
||||||
"bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-lVHORoVu1G61XVM8CRRqUsqr6w8kMlpuSpbPGpKUpmvrsoay6ymXAhT5lRPKyrGNamHUQTknmWdI59aRDCfLtQ=="],
|
"bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-zMLs2YIGB+/jxrYFXaFhVKX/GBt05UTF45lc9srcHc9JXGjEj+12CIo1CHLTAWatXMTqt0Jsu6ukWEoWVT/ayA=="],
|
||||||
|
|
||||||
"bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.3", "", { "os": "win32", "cpu": "x64" }, "sha512-vlspsFffctJlBnFfs2lW3QgDD6LyFu8VT18ryID7Qka5poTj0clGVRxz7DFRi7yva3GovEGw/82z/WVc5US8Pw=="],
|
"bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-Z5yAK28xrcm8Wb5k7TZ8FJKpOI/r+aVCRdlHYAqI2SDJFN3nD4mJs900X6kNVmG/xFzb5yOuKVYWGg+6ZXWbyA=="],
|
||||||
|
|
||||||
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
||||||
|
|
||||||
@@ -1704,7 +1732,7 @@
|
|||||||
|
|
||||||
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001753", "", {}, "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001754", "", {}, "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg=="],
|
||||||
|
|
||||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
||||||
|
|
||||||
@@ -1718,6 +1746,8 @@
|
|||||||
|
|
||||||
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
|
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
|
||||||
|
|
||||||
|
"chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
|
||||||
|
|
||||||
"cheerio": ["cheerio@1.0.0-rc.12", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "htmlparser2": "^8.0.1", "parse5": "^7.0.0", "parse5-htmlparser2-tree-adapter": "^7.0.0" } }, "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q=="],
|
"cheerio": ["cheerio@1.0.0-rc.12", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "htmlparser2": "^8.0.1", "parse5": "^7.0.0", "parse5-htmlparser2-tree-adapter": "^7.0.0" } }, "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q=="],
|
||||||
|
|
||||||
"cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="],
|
"cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="],
|
||||||
@@ -1742,6 +1772,8 @@
|
|||||||
|
|
||||||
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
|
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
|
||||||
|
|
||||||
|
"cloudflare": ["cloudflare@5.2.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-dVzqDpPFYR9ApEC9e+JJshFJZXcw4HzM8W+3DHzO5oy9+8rLC53G7x6fEf9A7/gSuSCxuvndzui5qJKftfIM9A=="],
|
||||||
|
|
||||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||||
|
|
||||||
"cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
|
"cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
|
||||||
@@ -1922,7 +1954,7 @@
|
|||||||
|
|
||||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.245", "", {}, "sha512-rdmGfW47ZhL/oWEJAY4qxRtdly2B98ooTJ0pdEI4jhVLZ6tNf8fPtov2wS1IRKwFJT92le3x4Knxiwzl7cPPpQ=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.250", "", {}, "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw=="],
|
||||||
|
|
||||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||||
|
|
||||||
@@ -2020,7 +2052,7 @@
|
|||||||
|
|
||||||
"expressive-code": ["expressive-code@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3", "@expressive-code/plugin-frames": "^0.41.3", "@expressive-code/plugin-shiki": "^0.41.3", "@expressive-code/plugin-text-markers": "^0.41.3" } }, "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg=="],
|
"expressive-code": ["expressive-code@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3", "@expressive-code/plugin-frames": "^0.41.3", "@expressive-code/plugin-shiki": "^0.41.3", "@expressive-code/plugin-text-markers": "^0.41.3" } }, "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg=="],
|
||||||
|
|
||||||
"exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
|
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
|
||||||
|
|
||||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||||
|
|
||||||
@@ -2068,11 +2100,15 @@
|
|||||||
|
|
||||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||||
|
|
||||||
"form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="],
|
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
||||||
|
|
||||||
|
"form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="],
|
||||||
|
|
||||||
|
"formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="],
|
||||||
|
|
||||||
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
||||||
|
|
||||||
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
|
"fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
|
||||||
|
|
||||||
"framer-motion": ["framer-motion@8.5.5", "", { "dependencies": { "@motionone/dom": "^10.15.3", "hey-listen": "^1.0.8", "tslib": "^2.4.0" }, "optionalDependencies": { "@emotion/is-prop-valid": "^0.8.2" }, "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }, "sha512-5IDx5bxkjWHWUF3CVJoSyUVOtrbAxtzYBBowRE2uYI/6VYhkEBD+rbTHEGuUmbGHRj6YqqSfoG7Aa1cLyWCrBA=="],
|
"framer-motion": ["framer-motion@8.5.5", "", { "dependencies": { "@motionone/dom": "^10.15.3", "hey-listen": "^1.0.8", "tslib": "^2.4.0" }, "optionalDependencies": { "@emotion/is-prop-valid": "^0.8.2" }, "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }, "sha512-5IDx5bxkjWHWUF3CVJoSyUVOtrbAxtzYBBowRE2uYI/6VYhkEBD+rbTHEGuUmbGHRj6YqqSfoG7Aa1cLyWCrBA=="],
|
||||||
|
|
||||||
@@ -2258,6 +2294,8 @@
|
|||||||
|
|
||||||
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||||
|
|
||||||
|
"humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="],
|
||||||
|
|
||||||
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
||||||
|
|
||||||
"i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="],
|
"i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="],
|
||||||
@@ -2668,7 +2706,7 @@
|
|||||||
|
|
||||||
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
||||||
|
|
||||||
"miniflare": ["miniflare@4.20251011.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251011.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-5oAaz6lqZus4QFwzEJiNtgpjZR2TBVwBeIhOW33V4gu+l23EukpKja831tFIX2o6sOD/hqZmKZHplOrWl3YGtQ=="],
|
"miniflare": ["miniflare@4.20251105.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251105.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-n+lCQbGLPjHFm5EKMohxCl+hLIki9rIlJSU9FkYKdJ62cGacetmTH5IgWUZhUFFM+NqhqZLOuWXTAsoZTm0hog=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
"minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
||||||
|
|
||||||
@@ -2716,6 +2754,8 @@
|
|||||||
|
|
||||||
"node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="],
|
"node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="],
|
||||||
|
|
||||||
|
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||||
|
|
||||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||||
|
|
||||||
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
||||||
@@ -2838,7 +2878,7 @@
|
|||||||
|
|
||||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||||
|
|
||||||
"path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="],
|
"path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="],
|
||||||
|
|
||||||
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
||||||
|
|
||||||
@@ -3056,7 +3096,7 @@
|
|||||||
|
|
||||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||||
|
|
||||||
"rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
|
"rollup": ["rollup@4.53.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.2", "@rollup/rollup-android-arm64": "4.53.2", "@rollup/rollup-darwin-arm64": "4.53.2", "@rollup/rollup-darwin-x64": "4.53.2", "@rollup/rollup-freebsd-arm64": "4.53.2", "@rollup/rollup-freebsd-x64": "4.53.2", "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", "@rollup/rollup-linux-arm-musleabihf": "4.53.2", "@rollup/rollup-linux-arm64-gnu": "4.53.2", "@rollup/rollup-linux-arm64-musl": "4.53.2", "@rollup/rollup-linux-loong64-gnu": "4.53.2", "@rollup/rollup-linux-ppc64-gnu": "4.53.2", "@rollup/rollup-linux-riscv64-gnu": "4.53.2", "@rollup/rollup-linux-riscv64-musl": "4.53.2", "@rollup/rollup-linux-s390x-gnu": "4.53.2", "@rollup/rollup-linux-x64-gnu": "4.53.2", "@rollup/rollup-linux-x64-musl": "4.53.2", "@rollup/rollup-openharmony-arm64": "4.53.2", "@rollup/rollup-win32-arm64-msvc": "4.53.2", "@rollup/rollup-win32-ia32-msvc": "4.53.2", "@rollup/rollup-win32-x64-gnu": "4.53.2", "@rollup/rollup-win32-x64-msvc": "4.53.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g=="],
|
||||||
|
|
||||||
"rollup-plugin-visualizer": ["rollup-plugin-visualizer@6.0.5", "", { "dependencies": { "open": "^8.0.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, "peerDependencies": { "rolldown": "1.x || ^1.0.0-beta", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg=="],
|
"rollup-plugin-visualizer": ["rollup-plugin-visualizer@6.0.5", "", { "dependencies": { "open": "^8.0.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, "peerDependencies": { "rolldown": "1.x || ^1.0.0-beta", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg=="],
|
||||||
|
|
||||||
@@ -3178,23 +3218,23 @@
|
|||||||
|
|
||||||
"sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="],
|
"sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="],
|
||||||
|
|
||||||
"sst": ["sst@3.17.22", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.22", "sst-darwin-x64": "3.17.22", "sst-linux-arm64": "3.17.22", "sst-linux-x64": "3.17.22", "sst-linux-x86": "3.17.22", "sst-win32-arm64": "3.17.22", "sst-win32-x64": "3.17.22", "sst-win32-x86": "3.17.22" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-C+XMTbm6fx+7eT+ESAMATqG7qV7+pyVfxYQb6osdH3jd4u91QW1VU/xlEru+RU1rs1ZE58ixXdRP75UGPn+gog=="],
|
"sst": ["sst@3.17.23", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.23", "sst-darwin-x64": "3.17.23", "sst-linux-arm64": "3.17.23", "sst-linux-x64": "3.17.23", "sst-linux-x86": "3.17.23", "sst-win32-arm64": "3.17.23", "sst-win32-x64": "3.17.23", "sst-win32-x86": "3.17.23" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-TwKgUgDnZdc1Swe+bvCNeyO4dQnYz5cTodMpYj3jlXZdK9/KNz0PVxT1f0u5E76i1pmilXrUBL/f7iiMPw4RDg=="],
|
||||||
|
|
||||||
"sst-darwin-arm64": ["sst-darwin-arm64@3.17.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-B2pKq1dWc60+7HfXQ6/9etskxxNv9axxlQKveCLQAuG2a3mmtv2/jcR0Ch3mvSTGtW+KfhzUXda2kj7nZ/phBA=="],
|
"sst-darwin-arm64": ["sst-darwin-arm64@3.17.23", "", { "os": "darwin", "cpu": "arm64" }, "sha512-R6kvmF+rUideOoU7KBs2SdvrIupoE+b+Dor/eq9Uo4Dojj7KvYDZI/EDm8sSCbbcx/opiWeyNqKtlnLEdCxE6g=="],
|
||||||
|
|
||||||
"sst-darwin-x64": ["sst-darwin-x64@3.17.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-flikYqXvhwwrS6x2FDOde+MQODHaZCIbUkVHYO3/gYo99rbAMQ8VpC/3LXnmnPEQkLOwWCSzLp4S4F9nG/PW2g=="],
|
"sst-darwin-x64": ["sst-darwin-x64@3.17.23", "", { "os": "darwin", "cpu": "x64" }, "sha512-WW4P1S35iYCifQXxD+sE3wuzcN+LHLpuKMaNoaBqEcWGZnH3IPaDJ7rpLF0arkDAo/z3jZmWWzOCkr0JuqJ8vQ=="],
|
||||||
|
|
||||||
"sst-linux-arm64": ["sst-linux-arm64@3.17.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-+pyD8Oej9js8XeCCebiEIde02vC5hc+bLl2/jR02K+9gYkGVJ6n5bkT8AlR8zWdS4FJKPyeJYUfjliT1T33j+g=="],
|
"sst-linux-arm64": ["sst-linux-arm64@3.17.23", "", { "os": "linux", "cpu": "arm64" }, "sha512-TjtNqgIh7RlAWgPLFCAt0mXvIB+J7WjmRvIRrAdX0mXsndOiBJ/DMOgXSLVsIWHCfPj8MIEot/hWpnJgXgIeag=="],
|
||||||
|
|
||||||
"sst-linux-x64": ["sst-linux-x64@3.17.22", "", { "os": "linux", "cpu": "x64" }, "sha512-A5p941edP9wgfgsbLUMeEPvi9JExj0OSaxgtFAC6/6BYoW4zruGAPzq206Ln6dNYP3gRdo5TJbSjio3F0ot8qg=="],
|
"sst-linux-x64": ["sst-linux-x64@3.17.23", "", { "os": "linux", "cpu": "x64" }, "sha512-qdqJiEbYfCjZlI3F/TA6eoIU7JXVkEEI/UMILNf2JWhky0KQdCW2Xyz+wb6c0msVJCWdUM/uj+1DaiP2eXvghw=="],
|
||||||
|
|
||||||
"sst-linux-x86": ["sst-linux-x86@3.17.22", "", { "os": "linux", "cpu": "none" }, "sha512-pFDIi+ZwH8GOvy5He9wsbAjRGf/sTGhGE/V480w0A6itb9BC4jQ9sblJkk3Jx/fP2g27pKN2RNz+ifOU+GrUYQ=="],
|
"sst-linux-x86": ["sst-linux-x86@3.17.23", "", { "os": "linux", "cpu": "none" }, "sha512-aGmUujIvoNlmAABEGsOgfY1rxD9koC6hN8bnTLbDI+oI/u/zjHYh50jsbL0p3TlaHpwF/lxP3xFSuT6IKp+KgA=="],
|
||||||
|
|
||||||
"sst-win32-arm64": ["sst-win32-arm64@3.17.22", "", { "os": "win32", "cpu": "arm64" }, "sha512-9KaIrk+Z6hLDNi9GShf9NLrZi9jC/NNGpUAn6HvTXr8c6HUyQzg6takMH8nrISGCPn92y+IYWqdglaqbgnJTog=="],
|
"sst-win32-arm64": ["sst-win32-arm64@3.17.23", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZxdkGqYDrrZGz98rijDCN+m5yuCcwD6Bc9/6hubLsvdpNlVorUqzpg801Ec97xSK0nIC9g6pNiRyxAcsQQstUg=="],
|
||||||
|
|
||||||
"sst-win32-x64": ["sst-win32-x64@3.17.22", "", { "os": "win32", "cpu": "x64" }, "sha512-cvzyet4octGHK7w05jPUSPmUdlAWyh8IzjB8Pcs873K9AUGJEtQCftOKZjXaFdIG9DTvFWCCBi9zdzClxT9jJg=="],
|
"sst-win32-x64": ["sst-win32-x64@3.17.23", "", { "os": "win32", "cpu": "x64" }, "sha512-yc9cor4MS49Ccy2tQCF1tf6M81yLeSGzGL+gjhUxpVKo2pN3bxl3w70eyU/mTXSEeyAmG9zEfbt6FNu4sy5cUA=="],
|
||||||
|
|
||||||
"sst-win32-x86": ["sst-win32-x86@3.17.22", "", { "os": "win32", "cpu": "none" }, "sha512-ol5icDJuHzG+AjbGbCIQoF8z3oiikTF9CtccdK/udqEF861DnngWzM99IY5TJvmJlN+38yOV0MY4XI5hM6SEQA=="],
|
"sst-win32-x86": ["sst-win32-x86@3.17.23", "", { "os": "win32", "cpu": "none" }, "sha512-DIp3s54IpNAfdYjSRt6McvkbEPQDMxUu6RUeRAd2C+FcTJgTloon/ghAPQBaDgu2VoVgymjcJARO/XyfKcCLOQ=="],
|
||||||
|
|
||||||
"stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
|
"stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
|
||||||
|
|
||||||
@@ -3480,6 +3520,8 @@
|
|||||||
|
|
||||||
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
||||||
|
|
||||||
|
"web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="],
|
||||||
|
|
||||||
"web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="],
|
"web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="],
|
||||||
|
|
||||||
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||||
@@ -3506,9 +3548,9 @@
|
|||||||
|
|
||||||
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||||
|
|
||||||
"workerd": ["workerd@1.20251011.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251011.0", "@cloudflare/workerd-darwin-arm64": "1.20251011.0", "@cloudflare/workerd-linux-64": "1.20251011.0", "@cloudflare/workerd-linux-arm64": "1.20251011.0", "@cloudflare/workerd-windows-64": "1.20251011.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Dq35TLPEJAw7BuYQMkN3p9rge34zWMU2Gnd4DSJFeVqld4+DAO2aPG7+We2dNIAyM97S8Y9BmHulbQ00E0HC7Q=="],
|
"workerd": ["workerd@1.20251105.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251105.0", "@cloudflare/workerd-darwin-arm64": "1.20251105.0", "@cloudflare/workerd-linux-64": "1.20251105.0", "@cloudflare/workerd-linux-arm64": "1.20251105.0", "@cloudflare/workerd-windows-64": "1.20251105.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-8D1UmsxrRr3Go7enbYCsYoiWeGn66u1WFNojPSgtjp7z8pV2cXskjr05vQ1OOzl7+rg1hDDofnCJqVwChMym8g=="],
|
||||||
|
|
||||||
"wrangler": ["wrangler@4.45.4", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.9", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251011.2", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20251011.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251011.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-niXT7B463wQi7WXIHjYK8txgWhuKQLrGmhjoR58SnPhlkq4wGjd3rFrkVyRc/O58clGTfs672BSGOph4XMoQKw=="],
|
"wrangler": ["wrangler@4.46.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.9", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251105.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20251105.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251014.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-WRROO7CL+MW/E44RMT4X7w32qPjufiPpGdey5D6H7iKzzVqfUkTRULxYBfWANiU1yGnsiCXQtu3Ap0G2TmohtA=="],
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||||
|
|
||||||
@@ -3538,7 +3580,7 @@
|
|||||||
|
|
||||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||||
|
|
||||||
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
|
"yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="],
|
||||||
|
|
||||||
"yocto-spinner": ["yocto-spinner@0.2.3", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ=="],
|
"yocto-spinner": ["yocto-spinner@0.2.3", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ=="],
|
||||||
|
|
||||||
@@ -3578,7 +3620,7 @@
|
|||||||
|
|
||||||
"@ai-sdk/amazon-bedrock/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
"@ai-sdk/amazon-bedrock/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||||
|
|
||||||
"@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-/iP1sKc6UdJgGH98OCly7sWJKv+J9G47PnTjIj40IJMUQKwDrUMyf7zOOfRtPwSuNifYhSoJQ4s1WltI65gJ/g=="],
|
"@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="],
|
||||||
|
|
||||||
"@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA=="],
|
"@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA=="],
|
||||||
|
|
||||||
@@ -3586,6 +3628,8 @@
|
|||||||
|
|
||||||
"@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA=="],
|
"@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA=="],
|
||||||
|
|
||||||
|
"@ai-sdk/mcp/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="],
|
||||||
|
|
||||||
"@astrojs/cloudflare/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
|
"@astrojs/cloudflare/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
|
||||||
|
|
||||||
"@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
|
"@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
|
||||||
@@ -3708,6 +3752,8 @@
|
|||||||
|
|
||||||
"@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
"@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
||||||
|
|
||||||
|
"@opencode-ai/desktop/@solidjs/router": ["@solidjs/router@0.15.3", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw=="],
|
||||||
|
|
||||||
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="],
|
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="],
|
||||||
|
|
||||||
"@opencode-ai/web/@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="],
|
"@opencode-ai/web/@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="],
|
||||||
@@ -3754,6 +3800,8 @@
|
|||||||
|
|
||||||
"@slack/web-api/eventemitter3": ["eventemitter3@3.1.2", "", {}, "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="],
|
"@slack/web-api/eventemitter3": ["eventemitter3@3.1.2", "", {}, "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="],
|
||||||
|
|
||||||
|
"@slack/web-api/form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="],
|
||||||
|
|
||||||
"@slack/web-api/p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="],
|
"@slack/web-api/p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="],
|
||||||
|
|
||||||
"@solidjs/start/shiki": ["shiki@1.29.2", "", { "dependencies": { "@shikijs/core": "1.29.2", "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/langs": "1.29.2", "@shikijs/themes": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg=="],
|
"@solidjs/start/shiki": ["shiki@1.29.2", "", { "dependencies": { "@shikijs/core": "1.29.2", "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/langs": "1.29.2", "@shikijs/themes": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg=="],
|
||||||
@@ -3778,8 +3826,6 @@
|
|||||||
|
|
||||||
"@tanstack/server-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
|
"@tanstack/server-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
|
||||||
|
|
||||||
"@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
|
|
||||||
|
|
||||||
"@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
"@vercel/nft/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
"@vercel/nft/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||||
@@ -3792,7 +3838,7 @@
|
|||||||
|
|
||||||
"accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
"accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||||
|
|
||||||
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-/iP1sKc6UdJgGH98OCly7sWJKv+J9G47PnTjIj40IJMUQKwDrUMyf7zOOfRtPwSuNifYhSoJQ4s1WltI65gJ/g=="],
|
"ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="],
|
||||||
|
|
||||||
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
@@ -3814,8 +3860,6 @@
|
|||||||
|
|
||||||
"astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
"astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||||
|
|
||||||
"axios/form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
|
||||||
|
|
||||||
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
||||||
|
|
||||||
"babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="],
|
"babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="],
|
||||||
@@ -3890,6 +3934,8 @@
|
|||||||
|
|
||||||
"gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
"gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
||||||
|
|
||||||
|
"gel/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"giget/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
"giget/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
||||||
@@ -3942,7 +3988,7 @@
|
|||||||
|
|
||||||
"named-placeholders/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
"named-placeholders/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
||||||
|
|
||||||
"nitropack/c12": ["c12@3.3.1", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-LcWQ01LT9tkoUINHgpIOv3mMs+Abv7oVCrtpMRi1PaapVEpWoMga5WuT7/DqFTu7URP9ftbOmimNw1KNIGh9DQ=="],
|
"nitropack/c12": ["c12@3.3.2", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-QkikB2X5voO1okL3QsES0N690Sn/K9WokXqUsDQsWy5SnYb+psYQFGA10iy1bZHj3fjISKsI67Q90gruvWWM3A=="],
|
||||||
|
|
||||||
"nitropack/globby": ["globby@15.0.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", "ignore": "^7.0.5", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw=="],
|
"nitropack/globby": ["globby@15.0.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", "ignore": "^7.0.5", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw=="],
|
||||||
|
|
||||||
@@ -4350,6 +4396,8 @@
|
|||||||
|
|
||||||
"@pierre/precision-diffs/shiki/@shikijs/types": ["@shikijs/types@3.14.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ=="],
|
"@pierre/precision-diffs/shiki/@shikijs/types": ["@shikijs/types@3.14.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ=="],
|
||||||
|
|
||||||
|
"@slack/web-api/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||||
|
|
||||||
"@slack/web-api/p-queue/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
|
"@slack/web-api/p-queue/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
|
||||||
|
|
||||||
"@slack/web-api/p-queue/p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="],
|
"@slack/web-api/p-queue/p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="],
|
||||||
@@ -4402,8 +4450,6 @@
|
|||||||
|
|
||||||
"astro/shiki/@shikijs/types": ["@shikijs/types@3.14.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ=="],
|
"astro/shiki/@shikijs/types": ["@shikijs/types@3.14.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ=="],
|
||||||
|
|
||||||
"axios/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
|
||||||
|
|
||||||
"babel-plugin-module-resolver/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="],
|
"babel-plugin-module-resolver/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="],
|
||||||
|
|
||||||
"babel-plugin-module-resolver/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
|
"babel-plugin-module-resolver/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
|
||||||
@@ -4700,6 +4746,8 @@
|
|||||||
|
|
||||||
"@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
"@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||||
|
|
||||||
|
"@slack/web-api/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||||
|
|
||||||
"@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="],
|
"@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="],
|
||||||
|
|
||||||
"@vercel/nft/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
"@vercel/nft/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||||
@@ -4708,8 +4756,6 @@
|
|||||||
|
|
||||||
"archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
"archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||||
|
|
||||||
"axios/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
|
||||||
|
|
||||||
"babel-plugin-module-resolver/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
"babel-plugin-module-resolver/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||||
|
|
||||||
"babel-plugin-module-resolver/glob/path-scurry/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
"babel-plugin-module-resolver/glob/path-scurry/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||||
|
|||||||
Generated
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1763618868,
|
||||||
|
"narHash": "sha256-v5afmLjn/uyD9EQuPBn7nZuaZVV9r+JerayK/4wvdWA=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a8d610af3f1a5fb71e23e08434d8d61a466fc942",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
description = "OpenCode development flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
nixpkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
systems = [
|
||||||
|
"aarch64-linux"
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-darwin"
|
||||||
|
"x86_64-darwin"
|
||||||
|
];
|
||||||
|
lib = nixpkgs.lib;
|
||||||
|
forEachSystem = lib.genAttrs systems;
|
||||||
|
pkgsFor = system: nixpkgs.legacyPackages.${system};
|
||||||
|
packageJson = builtins.fromJSON (builtins.readFile ./packages/opencode/package.json);
|
||||||
|
bunTarget = {
|
||||||
|
"aarch64-linux" = "bun-linux-arm64";
|
||||||
|
"x86_64-linux" = "bun-linux-x64";
|
||||||
|
"aarch64-darwin" = "bun-darwin-arm64";
|
||||||
|
"x86_64-darwin" = "bun-darwin-x64";
|
||||||
|
};
|
||||||
|
defaultNodeModules = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
|
hashesFile = "${./nix}/hashes.json";
|
||||||
|
hashesData =
|
||||||
|
if builtins.pathExists hashesFile then builtins.fromJSON (builtins.readFile hashesFile) else { };
|
||||||
|
nodeModulesHash = hashesData.nodeModules or defaultNodeModules;
|
||||||
|
modelsDev = forEachSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = pkgsFor system;
|
||||||
|
in
|
||||||
|
pkgs."models-dev"
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = forEachSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = pkgsFor system;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
bun
|
||||||
|
nodejs_20
|
||||||
|
pkg-config
|
||||||
|
openssl
|
||||||
|
git
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
packages = forEachSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = pkgsFor system;
|
||||||
|
mkNodeModules = pkgs.callPackage ./nix/node-modules.nix {
|
||||||
|
hash = nodeModulesHash;
|
||||||
|
};
|
||||||
|
mkPackage = pkgs.callPackage ./nix/opencode.nix { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = mkPackage {
|
||||||
|
version = packageJson.version;
|
||||||
|
src = ./.;
|
||||||
|
scripts = ./nix/scripts;
|
||||||
|
target = bunTarget.${system};
|
||||||
|
modelsDev = "${modelsDev.${system}}/dist/_api.json";
|
||||||
|
mkNodeModules = mkNodeModules;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
apps = forEachSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = pkgsFor system;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
opencode-dev = {
|
||||||
|
type = "app";
|
||||||
|
meta = {
|
||||||
|
description = "Nix devshell shell for OpenCode";
|
||||||
|
runtimeInputs = [ pkgs.bun ];
|
||||||
|
};
|
||||||
|
program = "${
|
||||||
|
pkgs.writeShellApplication {
|
||||||
|
name = "opencode-dev";
|
||||||
|
text = ''
|
||||||
|
exec bun run dev "$@"
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
}/bin/opencode-dev";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
+14
-43
@@ -171,9 +171,7 @@ try {
|
|||||||
const summary = await summarize(response)
|
const summary = await summarize(response)
|
||||||
await pushToLocalBranch(summary)
|
await pushToLocalBranch(summary)
|
||||||
}
|
}
|
||||||
const hasShared = prData.comments.nodes.some((c) =>
|
const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${useShareUrl()}/s/${shareId}`))
|
||||||
c.body.includes(`${useShareUrl()}/s/${shareId}`),
|
|
||||||
)
|
|
||||||
await updateComment(`${response}${footer({ image: !hasShared })}`)
|
await updateComment(`${response}${footer({ image: !hasShared })}`)
|
||||||
}
|
}
|
||||||
// Fork PR
|
// Fork PR
|
||||||
@@ -185,9 +183,7 @@ try {
|
|||||||
const summary = await summarize(response)
|
const summary = await summarize(response)
|
||||||
await pushToForkBranch(summary, prData)
|
await pushToForkBranch(summary, prData)
|
||||||
}
|
}
|
||||||
const hasShared = prData.comments.nodes.some((c) =>
|
const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${useShareUrl()}/s/${shareId}`))
|
||||||
c.body.includes(`${useShareUrl()}/s/${shareId}`),
|
|
||||||
)
|
|
||||||
await updateComment(`${response}${footer({ image: !hasShared })}`)
|
await updateComment(`${response}${footer({ image: !hasShared })}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,9 +364,7 @@ async function getAccessToken() {
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const responseJson = (await response.json()) as { error?: string }
|
const responseJson = (await response.json()) as { error?: string }
|
||||||
throw new Error(
|
throw new Error(`App token exchange failed: ${response.status} ${response.statusText} - ${responseJson.error}`)
|
||||||
`App token exchange failed: ${response.status} ${response.statusText} - ${responseJson.error}`,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseJson = (await response.json()) as { token: string }
|
const responseJson = (await response.json()) as { token: string }
|
||||||
@@ -411,12 +405,8 @@ async function getUserPrompt() {
|
|||||||
// ie. <img alt="Image" src="https://github.com/user-attachments/assets/xxxx" />
|
// ie. <img alt="Image" src="https://github.com/user-attachments/assets/xxxx" />
|
||||||
// ie. [api.json](https://github.com/user-attachments/files/21433810/api.json)
|
// ie. [api.json](https://github.com/user-attachments/files/21433810/api.json)
|
||||||
// ie. 
|
// ie. 
|
||||||
const mdMatches = prompt.matchAll(
|
const mdMatches = prompt.matchAll(/!?\[.*?\]\((https:\/\/github\.com\/user-attachments\/[^)]+)\)/gi)
|
||||||
/!?\[.*?\]\((https:\/\/github\.com\/user-attachments\/[^)]+)\)/gi,
|
const tagMatches = prompt.matchAll(/<img .*?src="(https:\/\/github\.com\/user-attachments\/[^"]+)" \/>/gi)
|
||||||
)
|
|
||||||
const tagMatches = prompt.matchAll(
|
|
||||||
/<img .*?src="(https:\/\/github\.com\/user-attachments\/[^"]+)" \/>/gi,
|
|
||||||
)
|
|
||||||
const matches = [...mdMatches, ...tagMatches].sort((a, b) => a.index - b.index)
|
const matches = [...mdMatches, ...tagMatches].sort((a, b) => a.index - b.index)
|
||||||
console.log("Images", JSON.stringify(matches, null, 2))
|
console.log("Images", JSON.stringify(matches, null, 2))
|
||||||
|
|
||||||
@@ -443,8 +433,7 @@ async function getUserPrompt() {
|
|||||||
|
|
||||||
// Replace img tag with file path, ie. @image.png
|
// Replace img tag with file path, ie. @image.png
|
||||||
const replacement = `@${filename}`
|
const replacement = `@${filename}`
|
||||||
prompt =
|
prompt = prompt.slice(0, start + offset) + replacement + prompt.slice(start + offset + tag.length)
|
||||||
prompt.slice(0, start + offset) + replacement + prompt.slice(start + offset + tag.length)
|
|
||||||
offset += replacement.length - tag.length
|
offset += replacement.length - tag.length
|
||||||
|
|
||||||
const contentType = res.headers.get("content-type")
|
const contentType = res.headers.get("content-type")
|
||||||
@@ -512,12 +501,7 @@ async function subscribeSessionEvents() {
|
|||||||
? JSON.stringify(part.state.input)
|
? JSON.stringify(part.state.input)
|
||||||
: "Unknown"
|
: "Unknown"
|
||||||
console.log()
|
console.log()
|
||||||
console.log(
|
console.log(color + `|`, "\x1b[0m\x1b[2m" + ` ${tool.padEnd(7, " ")}`, "", "\x1b[0m" + title)
|
||||||
color + `|`,
|
|
||||||
"\x1b[0m\x1b[2m" + ` ${tool.padEnd(7, " ")}`,
|
|
||||||
"",
|
|
||||||
"\x1b[0m" + title,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (part.type === "text") {
|
if (part.type === "text") {
|
||||||
@@ -729,8 +713,7 @@ async function assertPermissions() {
|
|||||||
throw new Error(`Failed to check permissions for user ${actor}: ${error}`)
|
throw new Error(`Failed to check permissions for user ${actor}: ${error}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!["admin", "write"].includes(permission))
|
if (!["admin", "write"].includes(permission)) throw new Error(`User ${actor} does not have write permissions`)
|
||||||
throw new Error(`User ${actor} does not have write permissions`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateComment(body: string) {
|
async function updateComment(body: string) {
|
||||||
@@ -774,9 +757,7 @@ function footer(opts?: { image?: boolean }) {
|
|||||||
|
|
||||||
return `<a href="${useShareUrl()}/s/${shareId}"><img width="200" alt="${titleAlt}" src="https://social-cards.sst.dev/opencode-share/${title64}.png?model=${providerID}/${modelID}&version=${session.version}&id=${shareId}" /></a>\n`
|
return `<a href="${useShareUrl()}/s/${shareId}"><img width="200" alt="${titleAlt}" src="https://social-cards.sst.dev/opencode-share/${title64}.png?model=${providerID}/${modelID}&version=${session.version}&id=${shareId}" /></a>\n`
|
||||||
})()
|
})()
|
||||||
const shareUrl = shareId
|
const shareUrl = shareId ? `[opencode session](${useShareUrl()}/s/${shareId}) | ` : ""
|
||||||
? `[opencode session](${useShareUrl()}/s/${shareId}) | `
|
|
||||||
: ""
|
|
||||||
return `\n\n${image}${shareUrl}[github run](${useEnvRunUrl()})`
|
return `\n\n${image}${shareUrl}[github run](${useEnvRunUrl()})`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -959,13 +940,9 @@ function buildPromptDataForPR(pr: GitHubPullRequest) {
|
|||||||
})
|
})
|
||||||
.map((c) => `- ${c.author.login} at ${c.createdAt}: ${c.body}`)
|
.map((c) => `- ${c.author.login} at ${c.createdAt}: ${c.body}`)
|
||||||
|
|
||||||
const files = (pr.files.nodes || []).map(
|
const files = (pr.files.nodes || []).map((f) => `- ${f.path} (${f.changeType}) +${f.additions}/-${f.deletions}`)
|
||||||
(f) => `- ${f.path} (${f.changeType}) +${f.additions}/-${f.deletions}`,
|
|
||||||
)
|
|
||||||
const reviewData = (pr.reviews.nodes || []).map((r) => {
|
const reviewData = (pr.reviews.nodes || []).map((r) => {
|
||||||
const comments = (r.comments.nodes || []).map(
|
const comments = (r.comments.nodes || []).map((c) => ` - ${c.path}:${c.line ?? "?"}: ${c.body}`)
|
||||||
(c) => ` - ${c.path}:${c.line ?? "?"}: ${c.body}`,
|
|
||||||
)
|
|
||||||
return [
|
return [
|
||||||
`- ${r.author.login} at ${r.submittedAt}:`,
|
`- ${r.author.login} at ${r.submittedAt}:`,
|
||||||
` - Review body: ${r.body}`,
|
` - Review body: ${r.body}`,
|
||||||
@@ -987,15 +964,9 @@ function buildPromptDataForPR(pr: GitHubPullRequest) {
|
|||||||
`Deletions: ${pr.deletions}`,
|
`Deletions: ${pr.deletions}`,
|
||||||
`Total Commits: ${pr.commits.totalCount}`,
|
`Total Commits: ${pr.commits.totalCount}`,
|
||||||
`Changed Files: ${pr.files.nodes.length} files`,
|
`Changed Files: ${pr.files.nodes.length} files`,
|
||||||
...(comments.length > 0
|
...(comments.length > 0 ? ["<pull_request_comments>", ...comments, "</pull_request_comments>"] : []),
|
||||||
? ["<pull_request_comments>", ...comments, "</pull_request_comments>"]
|
...(files.length > 0 ? ["<pull_request_changed_files>", ...files, "</pull_request_changed_files>"] : []),
|
||||||
: []),
|
...(reviewData.length > 0 ? ["<pull_request_reviews>", ...reviewData, "</pull_request_reviews>"] : []),
|
||||||
...(files.length > 0
|
|
||||||
? ["<pull_request_changed_files>", ...files, "</pull_request_changed_files>"]
|
|
||||||
: []),
|
|
||||||
...(reviewData.length > 0
|
|
||||||
? ["<pull_request_reviews>", ...reviewData, "</pull_request_reviews>"]
|
|
||||||
: []),
|
|
||||||
"</pull_request>",
|
"</pull_request>",
|
||||||
].join("\n")
|
].join("\n")
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -61,13 +61,7 @@ export const auth = new sst.cloudflare.Worker("AuthApi", {
|
|||||||
domain: `auth.${domain}`,
|
domain: `auth.${domain}`,
|
||||||
handler: "packages/console/function/src/auth.ts",
|
handler: "packages/console/function/src/auth.ts",
|
||||||
url: true,
|
url: true,
|
||||||
link: [
|
link: [database, authStorage, GITHUB_CLIENT_ID_CONSOLE, GITHUB_CLIENT_SECRET_CONSOLE, GOOGLE_CLIENT_ID],
|
||||||
database,
|
|
||||||
authStorage,
|
|
||||||
GITHUB_CLIENT_ID_CONSOLE,
|
|
||||||
GITHUB_CLIENT_SECRET_CONSOLE,
|
|
||||||
GOOGLE_CLIENT_ID,
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
@@ -112,6 +106,7 @@ const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", {
|
|||||||
const STRIPE_WEBHOOK_SECRET = new sst.Linkable("STRIPE_WEBHOOK_SECRET", {
|
const STRIPE_WEBHOOK_SECRET = new sst.Linkable("STRIPE_WEBHOOK_SECRET", {
|
||||||
properties: { value: stripeWebhook.secret },
|
properties: { value: stripeWebhook.secret },
|
||||||
})
|
})
|
||||||
|
const gatewayKv = new sst.cloudflare.Kv("GatewayKv")
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
@@ -142,6 +137,13 @@ new sst.cloudflare.x.SolidStart("Console", {
|
|||||||
EMAILOCTOPUS_API_KEY,
|
EMAILOCTOPUS_API_KEY,
|
||||||
AWS_SES_ACCESS_KEY_ID,
|
AWS_SES_ACCESS_KEY_ID,
|
||||||
AWS_SES_SECRET_ACCESS_KEY,
|
AWS_SES_SECRET_ACCESS_KEY,
|
||||||
|
...($dev
|
||||||
|
? [
|
||||||
|
new sst.Secret("CLOUDFLARE_DEFAULT_ACCOUNT_ID", process.env.CLOUDFLARE_DEFAULT_ACCOUNT_ID!),
|
||||||
|
new sst.Secret("CLOUDFLARE_API_TOKEN", process.env.CLOUDFLARE_API_TOKEN!),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
gatewayKv,
|
||||||
],
|
],
|
||||||
environment: {
|
environment: {
|
||||||
//VITE_DOCS_URL: web.url.apply((url) => url!),
|
//VITE_DOCS_URL: web.url.apply((url) => url!),
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"nodeModules": "sha256-bPiUpHGtgwVxHQHXBprpc6fFeJqW6/x7dwtQZBq29oU="
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
{ hash, lib, stdenvNoCC, bun, cacert, curl }:
|
||||||
|
args:
|
||||||
|
stdenvNoCC.mkDerivation {
|
||||||
|
pname = "opencode-node_modules";
|
||||||
|
version = args.version;
|
||||||
|
src = args.src;
|
||||||
|
|
||||||
|
impureEnvVars =
|
||||||
|
lib.fetchers.proxyImpureEnvVars
|
||||||
|
++ [
|
||||||
|
"GIT_PROXY_COMMAND"
|
||||||
|
"SOCKS_SERVER"
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [ bun cacert curl ];
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
export HOME=$(mktemp -d)
|
||||||
|
export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
|
||||||
|
bun install \
|
||||||
|
--cpu="*" \
|
||||||
|
--os="*" \
|
||||||
|
--frozen-lockfile \
|
||||||
|
--ignore-scripts \
|
||||||
|
--no-progress \
|
||||||
|
--linker=isolated
|
||||||
|
bun --bun ${args.canonicalizeScript}
|
||||||
|
bun --bun ${args.normalizeBinsScript}
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out
|
||||||
|
while IFS= read -r dir; do
|
||||||
|
rel="''${dir#./}"
|
||||||
|
dest="$out/$rel"
|
||||||
|
mkdir -p "$(dirname "$dest")"
|
||||||
|
cp -R "$dir" "$dest"
|
||||||
|
done < <(find . -type d -name node_modules -prune | sort)
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
dontFixup = true;
|
||||||
|
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHash = hash;
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
{ lib, stdenv, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }:
|
||||||
|
args:
|
||||||
|
let
|
||||||
|
scripts = args.scripts;
|
||||||
|
mkModules =
|
||||||
|
attrs:
|
||||||
|
args.mkNodeModules (
|
||||||
|
attrs
|
||||||
|
// {
|
||||||
|
canonicalizeScript = scripts + "/canonicalize-node-modules.ts";
|
||||||
|
normalizeBinsScript = scripts + "/normalize-bun-binaries.ts";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||||
|
pname = "opencode";
|
||||||
|
version = args.version;
|
||||||
|
|
||||||
|
src = args.src;
|
||||||
|
|
||||||
|
node_modules = mkModules {
|
||||||
|
version = finalAttrs.version;
|
||||||
|
src = finalAttrs.src;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
bun
|
||||||
|
makeBinaryWrapper
|
||||||
|
];
|
||||||
|
|
||||||
|
configurePhase = ''
|
||||||
|
runHook preConfigure
|
||||||
|
cp -R ${finalAttrs.node_modules}/. .
|
||||||
|
runHook postConfigure
|
||||||
|
'';
|
||||||
|
|
||||||
|
env.MODELS_DEV_API_JSON = args.modelsDev;
|
||||||
|
env.OPENCODE_VERSION = args.version;
|
||||||
|
env.OPENCODE_CHANNEL = "stable";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
cp ${scripts + "/bun-build.ts"} bun-build.ts
|
||||||
|
|
||||||
|
substituteInPlace bun-build.ts \
|
||||||
|
--replace '@VERSION@' "${finalAttrs.version}"
|
||||||
|
|
||||||
|
export BUN_COMPILE_TARGET=${args.target}
|
||||||
|
bun --bun bun-build.ts
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
dontStrip = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
cd packages/opencode
|
||||||
|
if [ ! -f opencode ]; then
|
||||||
|
echo "ERROR: opencode binary not found in $(pwd)"
|
||||||
|
ls -la
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f opencode-worker.js ]; then
|
||||||
|
echo "ERROR: opencode worker bundle not found in $(pwd)"
|
||||||
|
ls -la
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -Dm755 opencode $out/bin/opencode
|
||||||
|
install -Dm644 opencode-worker.js $out/bin/opencode-worker.js
|
||||||
|
if [ -f opencode-assets.manifest ]; then
|
||||||
|
while IFS= read -r asset; do
|
||||||
|
[ -z "$asset" ] && continue
|
||||||
|
if [ ! -f "$asset" ]; then
|
||||||
|
echo "ERROR: referenced asset \"$asset\" missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
install -Dm644 "$asset" "$out/bin/$(basename "$asset")"
|
||||||
|
done < opencode-assets.manifest
|
||||||
|
fi
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
postFixup = ''
|
||||||
|
wrapProgram "$out/bin/opencode" --prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]}
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "AI coding agent built for the terminal";
|
||||||
|
longDescription = ''
|
||||||
|
OpenCode is a terminal-based agent that can build anything.
|
||||||
|
It combines a TypeScript/JavaScript core with a Go-based TUI
|
||||||
|
to provide an interactive AI coding experience.
|
||||||
|
'';
|
||||||
|
homepage = "https://github.com/sst/opencode";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
platforms = [
|
||||||
|
"aarch64-linux"
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-darwin"
|
||||||
|
"x86_64-darwin"
|
||||||
|
];
|
||||||
|
mainProgram = "opencode";
|
||||||
|
};
|
||||||
|
})
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import solidPlugin from "./packages/opencode/node_modules/@opentui/solid/scripts/solid-plugin"
|
||||||
|
import path from "path"
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
const version = "@VERSION@"
|
||||||
|
const pkg = path.join(process.cwd(), "packages/opencode")
|
||||||
|
const parser = fs.realpathSync(path.join(pkg, "./node_modules/@opentui/core/parser.worker.js"))
|
||||||
|
const worker = "./src/cli/cmd/tui/worker.ts"
|
||||||
|
const target = process.env["BUN_COMPILE_TARGET"]
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
throw new Error("BUN_COMPILE_TARGET not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
process.chdir(pkg)
|
||||||
|
|
||||||
|
const manifestName = "opencode-assets.manifest"
|
||||||
|
const manifestPath = path.join(pkg, manifestName)
|
||||||
|
|
||||||
|
const readTrackedAssets = () => {
|
||||||
|
if (!fs.existsSync(manifestPath)) return []
|
||||||
|
return fs
|
||||||
|
.readFileSync(manifestPath, "utf8")
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line.length > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeTrackedAssets = () => {
|
||||||
|
for (const file of readTrackedAssets()) {
|
||||||
|
const filePath = path.join(pkg, file)
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
fs.rmSync(filePath, { force: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const assets = new Set<string>()
|
||||||
|
|
||||||
|
const addAsset = async (p: string) => {
|
||||||
|
const file = path.basename(p)
|
||||||
|
const dest = path.join(pkg, file)
|
||||||
|
await Bun.write(dest, Bun.file(p))
|
||||||
|
assets.add(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTrackedAssets()
|
||||||
|
|
||||||
|
const result = await Bun.build({
|
||||||
|
conditions: ["browser"],
|
||||||
|
tsconfig: "./tsconfig.json",
|
||||||
|
plugins: [solidPlugin],
|
||||||
|
sourcemap: "external",
|
||||||
|
entrypoints: ["./src/index.ts", parser, worker],
|
||||||
|
define: {
|
||||||
|
OPENCODE_VERSION: `'@VERSION@'`,
|
||||||
|
OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/" + path.relative(pkg, parser).replace(/\\/g, "/"),
|
||||||
|
OPENCODE_CHANNEL: "'latest'",
|
||||||
|
},
|
||||||
|
compile: {
|
||||||
|
target,
|
||||||
|
outfile: "opencode",
|
||||||
|
execArgv: ["--user-agent=opencode/" + version, '--env-file=""', "--"],
|
||||||
|
windows: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
console.error("Build failed!")
|
||||||
|
for (const log of result.logs) {
|
||||||
|
console.error(log)
|
||||||
|
}
|
||||||
|
throw new Error("Compilation failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
const assetOutputs = result.outputs?.filter((x) => x.kind === "asset") ?? []
|
||||||
|
for (const x of assetOutputs) {
|
||||||
|
await addAsset(x.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
const bundle = await Bun.build({
|
||||||
|
entrypoints: [worker],
|
||||||
|
tsconfig: "./tsconfig.json",
|
||||||
|
plugins: [solidPlugin],
|
||||||
|
target: "bun",
|
||||||
|
outdir: "./.opencode-worker",
|
||||||
|
sourcemap: "none",
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!bundle.success) {
|
||||||
|
console.error("Worker build failed!")
|
||||||
|
for (const log of bundle.logs) {
|
||||||
|
console.error(log)
|
||||||
|
}
|
||||||
|
throw new Error("Worker compilation failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
const workerAssets = bundle.outputs?.filter((x) => x.kind === "asset") ?? []
|
||||||
|
for (const x of workerAssets) {
|
||||||
|
await addAsset(x.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = bundle.outputs.find((x) => x.kind === "entry-point")
|
||||||
|
if (!output) {
|
||||||
|
throw new Error("Worker build produced no entry-point output")
|
||||||
|
}
|
||||||
|
|
||||||
|
const dest = path.join(pkg, "opencode-worker.js")
|
||||||
|
await Bun.write(dest, Bun.file(output.path))
|
||||||
|
fs.rmSync(path.dirname(output.path), { recursive: true, force: true })
|
||||||
|
|
||||||
|
const list = Array.from(assets)
|
||||||
|
await Bun.write(manifestPath, list.length > 0 ? list.join("\n") + "\n" : "")
|
||||||
|
|
||||||
|
console.log("Build successful!")
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import { lstat, mkdir, readdir, rm, symlink } from "fs/promises"
|
||||||
|
import { join, relative } from "path"
|
||||||
|
|
||||||
|
type SemverLike = {
|
||||||
|
valid: (value: string) => string | null
|
||||||
|
rcompare: (left: string, right: string) => number
|
||||||
|
}
|
||||||
|
|
||||||
|
type Entry = {
|
||||||
|
dir: string
|
||||||
|
version: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = process.cwd()
|
||||||
|
const bunRoot = join(root, "node_modules/.bun")
|
||||||
|
const linkRoot = join(bunRoot, "node_modules")
|
||||||
|
const directories = (await readdir(bunRoot)).sort()
|
||||||
|
const versions = new Map<string, Entry[]>()
|
||||||
|
|
||||||
|
for (const entry of directories) {
|
||||||
|
const full = join(bunRoot, entry)
|
||||||
|
const info = await lstat(full)
|
||||||
|
if (!info.isDirectory()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const marker = entry.lastIndexOf("@")
|
||||||
|
if (marker <= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const slug = entry.slice(0, marker).replace(/\+/g, "/")
|
||||||
|
const version = entry.slice(marker + 1)
|
||||||
|
const list = versions.get(slug) ?? []
|
||||||
|
list.push({ dir: full, version, label: entry })
|
||||||
|
versions.set(slug, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
const semverModule = (await import(join(bunRoot, "node_modules/semver"))) as
|
||||||
|
| SemverLike
|
||||||
|
| {
|
||||||
|
default: SemverLike
|
||||||
|
}
|
||||||
|
const semver = "default" in semverModule ? semverModule.default : semverModule
|
||||||
|
const selections = new Map<string, Entry>()
|
||||||
|
|
||||||
|
for (const [slug, list] of versions) {
|
||||||
|
list.sort((a, b) => {
|
||||||
|
const left = semver.valid(a.version)
|
||||||
|
const right = semver.valid(b.version)
|
||||||
|
if (left && right) {
|
||||||
|
const delta = semver.rcompare(left, right)
|
||||||
|
if (delta !== 0) {
|
||||||
|
return delta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (left && !right) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if (!left && right) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return b.version.localeCompare(a.version)
|
||||||
|
})
|
||||||
|
selections.set(slug, list[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
await rm(linkRoot, { recursive: true, force: true })
|
||||||
|
await mkdir(linkRoot, { recursive: true })
|
||||||
|
|
||||||
|
const rewrites: string[] = []
|
||||||
|
|
||||||
|
for (const [slug, entry] of Array.from(selections.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
||||||
|
const parts = slug.split("/")
|
||||||
|
const leaf = parts.pop()
|
||||||
|
if (!leaf) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const parent = join(linkRoot, ...parts)
|
||||||
|
await mkdir(parent, { recursive: true })
|
||||||
|
const linkPath = join(parent, leaf)
|
||||||
|
const desired = join(entry.dir, "node_modules", slug)
|
||||||
|
const relativeTarget = relative(parent, desired)
|
||||||
|
const resolved = relativeTarget.length === 0 ? "." : relativeTarget
|
||||||
|
await rm(linkPath, { recursive: true, force: true })
|
||||||
|
await symlink(resolved, linkPath)
|
||||||
|
rewrites.push(slug + " -> " + resolved)
|
||||||
|
}
|
||||||
|
|
||||||
|
rewrites.sort()
|
||||||
|
console.log("[canonicalize-node-modules] rebuilt", rewrites.length, "links")
|
||||||
|
for (const line of rewrites.slice(0, 20)) {
|
||||||
|
console.log(" ", line)
|
||||||
|
}
|
||||||
|
if (rewrites.length > 20) {
|
||||||
|
console.log(" ...")
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import { lstat, mkdir, readdir, rm, symlink } from "fs/promises"
|
||||||
|
import { join, relative } from "path"
|
||||||
|
|
||||||
|
type PackageManifest = {
|
||||||
|
name?: string
|
||||||
|
bin?: string | Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = process.cwd()
|
||||||
|
const bunRoot = join(root, "node_modules/.bun")
|
||||||
|
const bunEntries = (await safeReadDir(bunRoot)).sort()
|
||||||
|
let rewritten = 0
|
||||||
|
|
||||||
|
for (const entry of bunEntries) {
|
||||||
|
const modulesRoot = join(bunRoot, entry, "node_modules")
|
||||||
|
if (!(await exists(modulesRoot))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const binRoot = join(modulesRoot, ".bin")
|
||||||
|
await rm(binRoot, { recursive: true, force: true })
|
||||||
|
await mkdir(binRoot, { recursive: true })
|
||||||
|
|
||||||
|
const packageDirs = await collectPackages(modulesRoot)
|
||||||
|
for (const packageDir of packageDirs) {
|
||||||
|
const manifest = await readManifest(packageDir)
|
||||||
|
if (!manifest) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const binField = manifest.bin
|
||||||
|
if (!binField) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const seen = new Set<string>()
|
||||||
|
if (typeof binField === "string") {
|
||||||
|
const fallback = manifest.name ?? packageDir.split("/").pop()
|
||||||
|
if (fallback) {
|
||||||
|
await linkBinary(binRoot, fallback, packageDir, binField, seen)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const entries = Object.entries(binField).sort((a, b) => a[0].localeCompare(b[0]))
|
||||||
|
for (const [name, target] of entries) {
|
||||||
|
await linkBinary(binRoot, name, packageDir, target, seen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[normalize-bun-binaries] rewrote ${rewritten} links`)
|
||||||
|
|
||||||
|
async function collectPackages(modulesRoot: string) {
|
||||||
|
const found: string[] = []
|
||||||
|
const topLevel = (await safeReadDir(modulesRoot)).sort()
|
||||||
|
for (const name of topLevel) {
|
||||||
|
if (name === ".bin" || name === ".bun") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const full = join(modulesRoot, name)
|
||||||
|
if (!(await isDirectory(full))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (name.startsWith("@")) {
|
||||||
|
const scoped = (await safeReadDir(full)).sort()
|
||||||
|
for (const child of scoped) {
|
||||||
|
const scopedDir = join(full, child)
|
||||||
|
if (await isDirectory(scopedDir)) {
|
||||||
|
found.push(scopedDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found.push(full)
|
||||||
|
}
|
||||||
|
return found.sort()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readManifest(dir: string) {
|
||||||
|
const file = Bun.file(join(dir, "package.json"))
|
||||||
|
if (!(await file.exists())) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const data = (await file.json()) as PackageManifest
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function linkBinary(binRoot: string, name: string, packageDir: string, target: string, seen: Set<string>) {
|
||||||
|
if (!name || !target) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const normalizedName = normalizeBinName(name)
|
||||||
|
if (seen.has(normalizedName)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const resolved = join(packageDir, target)
|
||||||
|
const script = Bun.file(resolved)
|
||||||
|
if (!(await script.exists())) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
seen.add(normalizedName)
|
||||||
|
const destination = join(binRoot, normalizedName)
|
||||||
|
const relativeTarget = relative(binRoot, resolved) || "."
|
||||||
|
await rm(destination, { force: true })
|
||||||
|
await symlink(relativeTarget, destination)
|
||||||
|
rewritten++
|
||||||
|
}
|
||||||
|
|
||||||
|
async function exists(path: string) {
|
||||||
|
try {
|
||||||
|
await lstat(path)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function isDirectory(path: string) {
|
||||||
|
try {
|
||||||
|
const info = await lstat(path)
|
||||||
|
return info.isDirectory()
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function safeReadDir(path: string) {
|
||||||
|
try {
|
||||||
|
return await readdir(path)
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeBinName(name: string) {
|
||||||
|
const slash = name.lastIndexOf("/")
|
||||||
|
if (slash >= 0) {
|
||||||
|
return name.slice(slash + 1)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
Executable
+112
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DUMMY="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
||||||
|
SYSTEM=${SYSTEM:-x86_64-linux}
|
||||||
|
DEFAULT_HASH_FILE=${MODULES_HASH_FILE:-nix/hashes.json}
|
||||||
|
HASH_FILE=${HASH_FILE:-$DEFAULT_HASH_FILE}
|
||||||
|
|
||||||
|
if [ ! -f "$HASH_FILE" ]; then
|
||||||
|
cat >"$HASH_FILE" <<EOF
|
||||||
|
{
|
||||||
|
"nodeModules": "$DUMMY"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
if ! git ls-files --error-unmatch "$HASH_FILE" >/dev/null 2>&1; then
|
||||||
|
git add -N "$HASH_FILE" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DUMMY
|
||||||
|
export NIX_KEEP_OUTPUTS=1
|
||||||
|
export NIX_KEEP_DERIVATIONS=1
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -f "${JSON_OUTPUT:-}" "${BUILD_LOG:-}" "${TMP_EXPR:-}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
write_node_modules_hash() {
|
||||||
|
local value="$1"
|
||||||
|
local temp
|
||||||
|
temp=$(mktemp)
|
||||||
|
jq --arg value "$value" '.nodeModules = $value' "$HASH_FILE" >"$temp"
|
||||||
|
mv "$temp" "$HASH_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET="packages.${SYSTEM}.default"
|
||||||
|
MODULES_ATTR=".#packages.${SYSTEM}.default.node_modules"
|
||||||
|
CORRECT_HASH=""
|
||||||
|
|
||||||
|
DRV_PATH="$(nix eval --raw "${MODULES_ATTR}.drvPath")"
|
||||||
|
|
||||||
|
echo "Setting dummy node_modules outputHash for ${SYSTEM}..."
|
||||||
|
write_node_modules_hash "$DUMMY"
|
||||||
|
|
||||||
|
BUILD_LOG=$(mktemp)
|
||||||
|
JSON_OUTPUT=$(mktemp)
|
||||||
|
|
||||||
|
echo "Building node_modules for ${SYSTEM} to discover correct outputHash..."
|
||||||
|
echo "Attempting to realize derivation: ${DRV_PATH}"
|
||||||
|
REALISE_OUT=$(nix-store --realise "$DRV_PATH" --keep-failed 2>&1 | tee "$BUILD_LOG" || true)
|
||||||
|
|
||||||
|
BUILD_PATH=$(echo "$REALISE_OUT" | grep "^/nix/store/" | head -n1 || true)
|
||||||
|
if [ -n "$BUILD_PATH" ] && [ -d "$BUILD_PATH" ]; then
|
||||||
|
echo "Realized node_modules output: $BUILD_PATH"
|
||||||
|
CORRECT_HASH=$(nix hash path --sri "$BUILD_PATH" 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CORRECT_HASH" ]; then
|
||||||
|
CORRECT_HASH="$(grep -E 'got:\s+sha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | awk '{print $2}' | head -n1 || true)"
|
||||||
|
|
||||||
|
if [ -z "$CORRECT_HASH" ]; then
|
||||||
|
CORRECT_HASH="$(grep -A2 'hash mismatch' "$BUILD_LOG" | grep 'got:' | awk '{print $2}' | sed 's/sha256:/sha256-/' || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CORRECT_HASH" ]; then
|
||||||
|
echo "Searching for kept failed build directory..."
|
||||||
|
KEPT_DIR=$(grep -oE "build directory.*'[^']+'" "$BUILD_LOG" | grep -oE "'/[^']+'" | tr -d "'" | head -n1)
|
||||||
|
|
||||||
|
if [ -z "$KEPT_DIR" ]; then
|
||||||
|
KEPT_DIR=$(grep -oE '/nix/var/nix/builds/[^ ]+' "$BUILD_LOG" | head -n1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$KEPT_DIR" ] && [ -d "$KEPT_DIR" ]; then
|
||||||
|
echo "Found kept build directory: $KEPT_DIR"
|
||||||
|
if [ -d "$KEPT_DIR/build" ]; then
|
||||||
|
HASH_PATH="$KEPT_DIR/build"
|
||||||
|
else
|
||||||
|
HASH_PATH="$KEPT_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Attempting to hash: $HASH_PATH"
|
||||||
|
ls -la "$HASH_PATH" || true
|
||||||
|
|
||||||
|
if [ -d "$HASH_PATH/node_modules" ]; then
|
||||||
|
CORRECT_HASH=$(nix hash path --sri "$HASH_PATH" 2>/dev/null || true)
|
||||||
|
echo "Computed hash from kept build: $CORRECT_HASH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CORRECT_HASH" ]; then
|
||||||
|
echo "Failed to determine correct node_modules hash for ${SYSTEM}."
|
||||||
|
echo "Build log:"
|
||||||
|
cat "$BUILD_LOG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_node_modules_hash "$CORRECT_HASH"
|
||||||
|
|
||||||
|
jq -e --arg hash "$CORRECT_HASH" '.nodeModules == $hash' "$HASH_FILE" >/dev/null
|
||||||
|
|
||||||
|
echo "node_modules hash updated for ${SYSTEM}: $CORRECT_HASH"
|
||||||
|
|
||||||
|
rm -f "$BUILD_LOG"
|
||||||
|
unset BUILD_LOG
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://opencode.ai/config.json",
|
|
||||||
"plugin": ["opencode-openai-codex-auth"],
|
|
||||||
"mcp": {
|
|
||||||
"weather": {
|
|
||||||
"type": "local",
|
|
||||||
"command": ["bun", "x", "@h1deya/mcp-server-weather"]
|
|
||||||
},
|
|
||||||
"context7": {
|
|
||||||
"type": "remote",
|
|
||||||
"url": "https://mcp.context7.com/mcp",
|
|
||||||
"headers": {
|
|
||||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+5
-5
@@ -4,7 +4,7 @@
|
|||||||
"description": "AI-powered development tool",
|
"description": "AI-powered development tool",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "bun@1.3.1",
|
"packageManager": "bun@1.3.2",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
|
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
|
||||||
"typecheck": "bun turbo typecheck",
|
"typecheck": "bun turbo typecheck",
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
"@tsconfig/bun": "1.0.9",
|
"@tsconfig/bun": "1.0.9",
|
||||||
"@cloudflare/workers-types": "4.20251008.0",
|
"@cloudflare/workers-types": "4.20251008.0",
|
||||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||||
"@pierre/precision-diffs": "0.4.2",
|
"@pierre/precision-diffs": "0.4.4",
|
||||||
"@solidjs/meta": "0.29.4",
|
"@solidjs/meta": "0.29.4",
|
||||||
"@tailwindcss/vite": "4.1.11",
|
"@tailwindcss/vite": "4.1.11",
|
||||||
"diff": "8.0.2",
|
"diff": "8.0.2",
|
||||||
"ai": "5.0.8",
|
"ai": "5.0.97",
|
||||||
"hono": "4.7.10",
|
"hono": "4.7.10",
|
||||||
"fuzzysort": "3.1.0",
|
"fuzzysort": "3.1.0",
|
||||||
"luxon": "3.6.1",
|
"luxon": "3.6.1",
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
"@tsconfig/bun": "catalog:",
|
"@tsconfig/bun": "catalog:",
|
||||||
"husky": "9.1.7",
|
"husky": "9.1.7",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
"sst": "3.17.22",
|
"sst": "3.17.23",
|
||||||
"turbo": "2.5.6"
|
"turbo": "2.5.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"printWidth": 100
|
"printWidth": 120
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"esbuild",
|
"esbuild",
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ app.config.timestamp_*.js
|
|||||||
# Temp
|
# Temp
|
||||||
gitignore
|
gitignore
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
public/sitemap.xml
|
||||||
|
|
||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
@@ -5,21 +5,22 @@
|
|||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"dev": "vinxi dev --host 0.0.0.0",
|
"dev": "vinxi dev --host 0.0.0.0",
|
||||||
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
|
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
|
||||||
"build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
|
"build": "./script/generate-sitemap.ts && vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
|
||||||
"start": "vinxi start",
|
"start": "vinxi start",
|
||||||
"version": "1.0.36"
|
"version": "1.0.85"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
|
"@jsx-email/render": "1.1.1",
|
||||||
|
"@kobalte/core": "catalog:",
|
||||||
|
"@openauthjs/openauth": "catalog:",
|
||||||
"@opencode-ai/console-core": "workspace:*",
|
"@opencode-ai/console-core": "workspace:*",
|
||||||
"@opencode-ai/console-mail": "workspace:*",
|
"@opencode-ai/console-mail": "workspace:*",
|
||||||
"@openauthjs/openauth": "catalog:",
|
|
||||||
"@kobalte/core": "catalog:",
|
|
||||||
"@jsx-email/render": "1.1.1",
|
|
||||||
"@opencode-ai/console-resource": "workspace:*",
|
"@opencode-ai/console-resource": "workspace:*",
|
||||||
"@solidjs/meta": "^0.29.4",
|
"@solidjs/meta": "^0.29.4",
|
||||||
"@solidjs/router": "^0.15.0",
|
"@solidjs/router": "^0.15.0",
|
||||||
"@solidjs/start": "^1.1.0",
|
"@solidjs/start": "^1.1.0",
|
||||||
|
"chart.js": "4.5.1",
|
||||||
"solid-js": "catalog:",
|
"solid-js": "catalog:",
|
||||||
"vinxi": "^0.5.7",
|
"vinxi": "^0.5.7",
|
||||||
"zod": "catalog:"
|
"zod": "catalog:"
|
||||||
|
|||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
import { readdir, writeFile } from "fs/promises"
|
||||||
|
import { join, dirname } from "path"
|
||||||
|
import { fileURLToPath } from "url"
|
||||||
|
import { config } from "../src/config.js"
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const BASE_URL = config.baseUrl
|
||||||
|
const PUBLIC_DIR = join(__dirname, "../public")
|
||||||
|
const ROUTES_DIR = join(__dirname, "../src/routes")
|
||||||
|
const DOCS_DIR = join(__dirname, "../../../web/src/content/docs")
|
||||||
|
|
||||||
|
interface SitemapEntry {
|
||||||
|
url: string
|
||||||
|
priority: number
|
||||||
|
changefreq: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMainRoutes(): Promise<SitemapEntry[]> {
|
||||||
|
const routes: SitemapEntry[] = []
|
||||||
|
|
||||||
|
// Add main static routes
|
||||||
|
const staticRoutes = [
|
||||||
|
{ path: "/", priority: 1.0, changefreq: "daily" },
|
||||||
|
{ path: "/enterprise", priority: 0.8, changefreq: "weekly" },
|
||||||
|
{ path: "/brand", priority: 0.6, changefreq: "monthly" },
|
||||||
|
{ path: "/zen", priority: 0.8, changefreq: "weekly" },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const route of staticRoutes) {
|
||||||
|
routes.push({
|
||||||
|
url: `${BASE_URL}${route.path}`,
|
||||||
|
priority: route.priority,
|
||||||
|
changefreq: route.changefreq,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDocsRoutes(): Promise<SitemapEntry[]> {
|
||||||
|
const routes: SitemapEntry[] = []
|
||||||
|
|
||||||
|
try {
|
||||||
|
const files = await readdir(DOCS_DIR)
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (!file.endsWith(".mdx")) continue
|
||||||
|
|
||||||
|
const slug = file.replace(".mdx", "")
|
||||||
|
const path = slug === "index" ? "/docs/" : `/docs/${slug}`
|
||||||
|
|
||||||
|
routes.push({
|
||||||
|
url: `${BASE_URL}${path}`,
|
||||||
|
priority: slug === "index" ? 0.9 : 0.7,
|
||||||
|
changefreq: "weekly",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading docs directory:", error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSitemapXML(entries: SitemapEntry[]): string {
|
||||||
|
const urls = entries
|
||||||
|
.map(
|
||||||
|
(entry) => ` <url>
|
||||||
|
<loc>${entry.url}</loc>
|
||||||
|
<changefreq>${entry.changefreq}</changefreq>
|
||||||
|
<priority>${entry.priority}</priority>
|
||||||
|
</url>`,
|
||||||
|
)
|
||||||
|
.join("\n")
|
||||||
|
|
||||||
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
${urls}
|
||||||
|
</urlset>`
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log("Generating sitemap...")
|
||||||
|
|
||||||
|
const mainRoutes = await getMainRoutes()
|
||||||
|
const docsRoutes = await getDocsRoutes()
|
||||||
|
|
||||||
|
const allRoutes = [...mainRoutes, ...docsRoutes]
|
||||||
|
|
||||||
|
console.log(`Found ${mainRoutes.length} main routes`)
|
||||||
|
console.log(`Found ${docsRoutes.length} docs routes`)
|
||||||
|
console.log(`Total: ${allRoutes.length} routes`)
|
||||||
|
|
||||||
|
const xml = generateSitemapXML(allRoutes)
|
||||||
|
|
||||||
|
const outputPath = join(PUBLIC_DIR, "sitemap.xml")
|
||||||
|
await writeFile(outputPath, xml, "utf-8")
|
||||||
|
|
||||||
|
console.log(`✓ Sitemap generated at ${outputPath}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -12,10 +12,7 @@ export default function App() {
|
|||||||
root={(props) => (
|
root={(props) => (
|
||||||
<MetaProvider>
|
<MetaProvider>
|
||||||
<Title>opencode</Title>
|
<Title>opencode</Title>
|
||||||
<Meta
|
<Meta name="description" content="OpenCode - The AI coding agent built for the terminal." />
|
||||||
name="description"
|
|
||||||
content="OpenCode - The AI coding agent built for the terminal."
|
|
||||||
/>
|
|
||||||
<Suspense>{props.children}</Suspense>
|
<Suspense>{props.children}</Suspense>
|
||||||
</MetaProvider>
|
</MetaProvider>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -13,10 +13,7 @@ export function Faq(props: ParentProps & { question: string }) {
|
|||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path d="M12.5 11.5H19V12.5H12.5V19H11.5V12.5H5V11.5H11.5V5H12.5V11.5Z" fill="currentColor" />
|
||||||
d="M12.5 11.5H19V12.5H12.5V19H11.5V12.5H5V11.5H11.5V5H12.5V11.5Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
<svg
|
<svg
|
||||||
data-slot="faq-icon-minus"
|
data-slot="faq-icon-minus"
|
||||||
|
|||||||
@@ -9,23 +9,10 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
<path d="M13.7124 9.14333V4.5719H18.2838V9.14333H13.7124Z" fill="currentColor" />
|
<path d="M13.7124 9.14333V4.5719H18.2838V9.14333H13.7124Z" fill="currentColor" />
|
||||||
<path d="M13.7124 13.7136V9.14221H18.2838V13.7136H13.7124Z" fill="currentColor" />
|
<path d="M13.7124 13.7136V9.14221H18.2838V13.7136H13.7124Z" fill="currentColor" />
|
||||||
<path d="M0 18.2857V13.7142H4.57143V18.2857H0Z" fill="currentColor" fill-opacity="0.2" />
|
<path d="M0 18.2857V13.7142H4.57143V18.2857H0Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
<rect
|
<rect width="4.57143" height="4.57143" transform="translate(4.57178 13.7141)" fill="currentColor" />
|
||||||
width="4.57143"
|
<path d="M4.57178 18.2855V13.7141H9.14321V18.2855H4.57178Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
height="4.57143"
|
|
||||||
transform="translate(4.57178 13.7141)"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M4.57178 18.2855V13.7141H9.14321V18.2855H4.57178Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M9.1438 18.2855V13.7141H13.7152V18.2855H9.1438Z" fill="currentColor" />
|
<path d="M9.1438 18.2855V13.7141H13.7152V18.2855H9.1438Z" fill="currentColor" />
|
||||||
<path
|
<path d="M13.7156 18.2855V13.7141H18.287V18.2855H13.7156Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M13.7156 18.2855V13.7141H18.287V18.2855H13.7156Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<rect width="4.57143" height="4.57143" transform="translate(0 18.2859)" fill="currentColor" />
|
<rect width="4.57143" height="4.57143" transform="translate(0 18.2859)" fill="currentColor" />
|
||||||
<path d="M0 22.8572V18.2858H4.57143V22.8572H0Z" fill="currentColor" fill-opacity="0.2" />
|
<path d="M0 22.8572V18.2858H4.57143V22.8572H0Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
<rect
|
<rect
|
||||||
@@ -36,16 +23,8 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
fill-opacity="0.2"
|
fill-opacity="0.2"
|
||||||
/>
|
/>
|
||||||
<path d="M4.57178 22.8573V18.2859H9.14321V22.8573H4.57178Z" fill="currentColor" />
|
<path d="M4.57178 22.8573V18.2859H9.14321V22.8573H4.57178Z" fill="currentColor" />
|
||||||
<path
|
<path d="M9.1438 22.8573V18.2859H13.7152V22.8573H9.1438Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M9.1438 22.8573V18.2859H13.7152V22.8573H9.1438Z"
|
<path d="M13.7156 22.8573V18.2859H18.287V22.8573H13.7156Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M13.7156 22.8573V18.2859H18.287V22.8573H13.7156Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M0 27.4292V22.8578H4.57143V27.4292H0Z" fill="currentColor" />
|
<path d="M0 27.4292V22.8578H4.57143V27.4292H0Z" fill="currentColor" />
|
||||||
<path d="M4.57178 27.4292V22.8578H9.14321V27.4292H4.57178Z" fill="currentColor" />
|
<path d="M4.57178 27.4292V22.8578H9.14321V27.4292H4.57178Z" fill="currentColor" />
|
||||||
<path d="M9.1438 27.4276V22.8562H13.7152V27.4276H9.1438Z" fill="currentColor" />
|
<path d="M9.1438 27.4276V22.8562H13.7152V27.4276H9.1438Z" fill="currentColor" />
|
||||||
@@ -61,21 +40,9 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
<path d="M32.001 18.2855V13.7141H36.5724V18.2855H32.001Z" fill="currentColor" />
|
<path d="M32.001 18.2855V13.7141H36.5724V18.2855H32.001Z" fill="currentColor" />
|
||||||
<path d="M36.5698 18.2855V13.7141H41.1413V18.2855H36.5698Z" fill="currentColor" />
|
<path d="M36.5698 18.2855V13.7141H41.1413V18.2855H36.5698Z" fill="currentColor" />
|
||||||
<path d="M22.8572 22.8573V18.2859H27.4286V22.8573H22.8572Z" fill="currentColor" />
|
<path d="M22.8572 22.8573V18.2859H27.4286V22.8573H22.8572Z" fill="currentColor" />
|
||||||
<path
|
<path d="M27.4292 22.8573V18.2859H32.0006V22.8573H27.4292Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M27.4292 22.8573V18.2859H32.0006V22.8573H27.4292Z"
|
<path d="M32.001 22.8573V18.2859H36.5724V22.8573H32.001Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill="currentColor"
|
<path d="M36.5698 22.8573V18.2859H41.1413V22.8573H36.5698Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M32.001 22.8573V18.2859H36.5724V22.8573H32.001Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M36.5698 22.8573V18.2859H41.1413V22.8573H36.5698Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M22.8572 27.4292V22.8578H27.4286V27.4292H22.8572Z" fill="currentColor" />
|
<path d="M22.8572 27.4292V22.8578H27.4286V27.4292H22.8572Z" fill="currentColor" />
|
||||||
<path d="M27.4292 27.4276V22.8562H32.0006V27.4276H27.4292Z" fill="currentColor" />
|
<path d="M27.4292 27.4276V22.8562H32.0006V27.4276H27.4292Z" fill="currentColor" />
|
||||||
<path d="M32.001 27.4276V22.8562H36.5724V27.4276H32.001Z" fill="currentColor" />
|
<path d="M32.001 27.4276V22.8562H36.5724V27.4276H32.001Z" fill="currentColor" />
|
||||||
@@ -86,40 +53,16 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
<path d="M45.7144 13.7136V9.14221H50.2858V13.7136H45.7144Z" fill="currentColor" />
|
<path d="M45.7144 13.7136V9.14221H50.2858V13.7136H45.7144Z" fill="currentColor" />
|
||||||
<path d="M59.4299 13.7152V9.1438H64.0014V13.7152H59.4299Z" fill="currentColor" />
|
<path d="M59.4299 13.7152V9.1438H64.0014V13.7152H59.4299Z" fill="currentColor" />
|
||||||
<path d="M45.7144 18.2855V13.7141H50.2858V18.2855H45.7144Z" fill="currentColor" />
|
<path d="M45.7144 18.2855V13.7141H50.2858V18.2855H45.7144Z" fill="currentColor" />
|
||||||
<path
|
<path d="M50.2861 18.2857V13.7142H54.8576V18.2857H50.2861Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M50.2861 18.2857V13.7142H54.8576V18.2857H50.2861Z"
|
<path d="M54.8579 18.2855V13.7141H59.4293V18.2855H54.8579Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M54.8579 18.2855V13.7141H59.4293V18.2855H54.8579Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M59.4299 18.2855V13.7141H64.0014V18.2855H59.4299Z" fill="currentColor" />
|
<path d="M59.4299 18.2855V13.7141H64.0014V18.2855H59.4299Z" fill="currentColor" />
|
||||||
<path d="M45.7144 22.8573V18.2859H50.2858V22.8573H45.7144Z" fill="currentColor" />
|
<path d="M45.7144 22.8573V18.2859H50.2858V22.8573H45.7144Z" fill="currentColor" />
|
||||||
<path
|
<path d="M50.2861 22.8572V18.2858H54.8576V22.8572H50.2861Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M50.2861 22.8572V18.2858H54.8576V22.8572H50.2861Z"
|
<path d="M54.8579 22.8573V18.2859H59.4293V22.8573H54.8579Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M54.8579 22.8573V18.2859H59.4293V22.8573H54.8579Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M59.4299 22.8573V18.2859H64.0014V22.8573H59.4299Z" fill="currentColor" />
|
<path d="M59.4299 22.8573V18.2859H64.0014V22.8573H59.4299Z" fill="currentColor" />
|
||||||
<path d="M45.7144 27.4292V22.8578H50.2858V27.4292H45.7144Z" fill="currentColor" />
|
<path d="M45.7144 27.4292V22.8578H50.2858V27.4292H45.7144Z" fill="currentColor" />
|
||||||
<path
|
<path d="M50.2861 27.4286V22.8572H54.8576V27.4286H50.2861Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
d="M50.2861 27.4286V22.8572H54.8576V27.4286H50.2861Z"
|
<path d="M54.8579 27.4285V22.8571H59.4293V27.4285H54.8579Z" fill="currentColor" fill-opacity="0.2" />
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M54.8579 27.4285V22.8571H59.4293V27.4285H54.8579Z"
|
|
||||||
fill="currentColor"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
/>
|
|
||||||
<path d="M59.4299 27.4292V22.8578H64.0014V27.4292H59.4299Z" fill="currentColor" />
|
<path d="M59.4299 27.4292V22.8578H64.0014V27.4292H59.4299Z" fill="currentColor" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
@@ -127,14 +70,7 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
|
|
||||||
export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{...props}
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z"
|
d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -147,20 +83,8 @@ export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
|
|
||||||
export function IconCheck(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconCheck(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{...props}
|
<path d="M2.75 15.0938L9 20.25L21.25 3.75" stroke="#03B000" stroke-width="2" stroke-linecap="square" />
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M2.75 15.0938L9 20.25L21.25 3.75"
|
|
||||||
stroke="#03B000"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="square"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -189,14 +113,7 @@ export function IconStripe(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
|
|
||||||
export function IconChevron(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconChevron(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg {...props} width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{...props}
|
|
||||||
width="8"
|
|
||||||
height="6"
|
|
||||||
viewBox="0 0 8 6"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M4.00024 5.04041L7.37401 1.66663L6.66691 0.959525L4.00024 3.62619L1.33357 0.959525L0.626465 1.66663L4.00024 5.04041Z"
|
d="M4.00024 5.04041L7.37401 1.66663L6.66691 0.959525L4.00024 3.62619L1.33357 0.959525L0.626465 1.66663L4.00024 5.04041Z"
|
||||||
@@ -207,14 +124,7 @@ export function IconChevron(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
|
|
||||||
export function IconWorkspaceLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconWorkspaceLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg {...props} width="24" height="30" viewBox="0 0 24 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{...props}
|
|
||||||
width="24"
|
|
||||||
height="30"
|
|
||||||
viewBox="0 0 24 30"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z" fill="currentColor" />
|
<path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z" fill="currentColor" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
@@ -234,10 +144,7 @@ export function IconOpenAI(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
export function IconAnthropic(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconAnthropic(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg {...props} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg {...props} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path
|
<path fill="currentColor" d="M13.7891 3.93188L20.2223 20.068H23.7502L17.317 3.93188H13.7891Z" />
|
||||||
fill="currentColor"
|
|
||||||
d="M13.7891 3.93188L20.2223 20.068H23.7502L17.317 3.93188H13.7891Z"
|
|
||||||
/>
|
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M6.32538 13.6827L8.52662 8.01201L10.7279 13.6827H6.32538ZM6.68225 3.93188L0.25 20.068H3.84652L5.16202 16.6794H11.8914L13.2067 20.068H16.8033L10.371 3.93188H6.68225Z"
|
d="M6.32538 13.6827L8.52662 8.01201L10.7279 13.6827H6.32538ZM6.68225 3.93188L0.25 20.068H3.84652L5.16202 16.6794H11.8914L13.2067 20.068H16.8033L10.371 3.93188H6.68225Z"
|
||||||
@@ -295,6 +202,14 @@ export function IconZai(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IconGoogle(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} viewBox="0 0 50 50" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M49.04,24.001l-1.082-0.043h-0.001C36.134,23.492,26.508,13.866,26.042,2.043L25.999,0.96C25.978,0.424,25.537,0,25,0 s-0.978,0.424-0.999,0.96l-0.043,1.083C23.492,13.866,13.866,23.492,2.042,23.958L0.96,24.001C0.424,24.022,0,24.463,0,25 c0,0.537,0.424,0.978,0.961,0.999l1.082,0.042c11.823,0.467,21.449,10.093,21.915,21.916l0.043,1.083C24.022,49.576,24.463,50,25,50 s0.978-0.424,0.999-0.96l0.043-1.083c0.466-11.823,10.092-21.449,21.915-21.916l1.082-0.042C49.576,25.978,50,25.537,50,25 C50,24.463,49.576,24.022,49.04,24.001z"></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function IconStealth(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
export function IconStealth(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 18" fill="none">
|
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 18" fill="none">
|
||||||
@@ -305,3 +220,30 @@ export function IconStealth(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
|||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IconChevronLeft(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} viewBox="0 0 20 20" fill="none">
|
||||||
|
<path d="M12 15L7 10L12 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconChevronRight(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} viewBox="0 0 20 20" fill="none">
|
||||||
|
<path d="M8 5L13 10L8 15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconBreakdown(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||||
|
<path d="M2 12L2 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||||
|
<path d="M6 12L6 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||||
|
<path d="M10 12L10 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||||
|
<path d="M14 12L14 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
* Application-wide constants and configuration
|
* Application-wide constants and configuration
|
||||||
*/
|
*/
|
||||||
export const config = {
|
export const config = {
|
||||||
|
// Base URL
|
||||||
|
baseUrl: "https://opencode.ai",
|
||||||
|
|
||||||
// GitHub
|
// GitHub
|
||||||
github: {
|
github: {
|
||||||
repoUrl: "https://github.com/sst/opencode",
|
repoUrl: "https://github.com/sst/opencode",
|
||||||
@@ -19,8 +22,8 @@ export const config = {
|
|||||||
|
|
||||||
// Static stats (used on landing page)
|
// Static stats (used on landing page)
|
||||||
stats: {
|
stats: {
|
||||||
contributors: "250",
|
contributors: "300",
|
||||||
commits: "3,500",
|
commits: "4,000",
|
||||||
monthlyUsers: "300,000",
|
monthlyUsers: "300,000",
|
||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ export const github = query(async () => {
|
|||||||
"User-Agent":
|
"User-Agent":
|
||||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
||||||
}
|
}
|
||||||
const apiBaseUrl = config.github.repoUrl.replace(
|
const apiBaseUrl = config.github.repoUrl.replace("https://github.com/", "https://api.github.com/repos/")
|
||||||
"https://github.com/",
|
|
||||||
"https://api.github.com/repos/",
|
|
||||||
)
|
|
||||||
try {
|
try {
|
||||||
const [meta, releases, contributors] = await Promise.all([
|
const [meta, releases, contributors] = await Promise.all([
|
||||||
fetch(apiBaseUrl, { headers }).then((res) => res.json()),
|
fetch(apiBaseUrl, { headers }).then((res) => res.json()),
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import type { APIEvent } from "@solidjs/start/server"
|
|||||||
import { AuthClient } from "~/context/auth"
|
import { AuthClient } from "~/context/auth"
|
||||||
|
|
||||||
export async function GET(input: APIEvent) {
|
export async function GET(input: APIEvent) {
|
||||||
const result = await AuthClient.authorize(
|
const result = await AuthClient.authorize(new URL("./callback", input.request.url).toString(), "code")
|
||||||
new URL("./callback", input.request.url).toString(),
|
|
||||||
"code",
|
|
||||||
)
|
|
||||||
return Response.redirect(result.url, 302)
|
return Response.redirect(result.url, 302)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,7 @@
|
|||||||
[data-component="brand-content"] {
|
[data-component="brand-content"] {
|
||||||
padding: 4rem 5rem;
|
padding: 4rem 5rem;
|
||||||
|
|
||||||
h2 {
|
h1 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--color-text-strong);
|
color: var(--color-text-strong);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import "./index.css"
|
import "./index.css"
|
||||||
import { Title, Meta } from "@solidjs/meta"
|
import { Title, Meta, Link } from "@solidjs/meta"
|
||||||
import { Header } from "~/component/header"
|
import { Header } from "~/component/header"
|
||||||
|
import { config } from "~/config"
|
||||||
import { Footer } from "~/component/footer"
|
import { Footer } from "~/component/footer"
|
||||||
import { Legal } from "~/component/legal"
|
import { Legal } from "~/component/legal"
|
||||||
import previewLogoLight from "../../asset/brand/preview-opencode-logo-light.png"
|
import previewLogoLight from "../../asset/brand/preview-opencode-logo-light.png"
|
||||||
@@ -53,26 +54,21 @@ export default function Brand() {
|
|||||||
return (
|
return (
|
||||||
<main data-page="enterprise">
|
<main data-page="enterprise">
|
||||||
<Title>OpenCode | Brand</Title>
|
<Title>OpenCode | Brand</Title>
|
||||||
|
<Link rel="canonical" href={`${config.baseUrl}/brand`} />
|
||||||
<Meta name="description" content="OpenCode brand guidelines" />
|
<Meta name="description" content="OpenCode brand guidelines" />
|
||||||
<div data-component="container">
|
<div data-component="container">
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<div data-component="content">
|
<div data-component="content">
|
||||||
<section data-component="brand-content">
|
<section data-component="brand-content">
|
||||||
<h2>Brand guidelines</h2>
|
<h1>Brand guidelines</h1>
|
||||||
<p>Resources and assets to help you work with the OpenCode brand.</p>
|
<p>Resources and assets to help you work with the OpenCode brand.</p>
|
||||||
<button
|
<button
|
||||||
data-component="download-button"
|
data-component="download-button"
|
||||||
onClick={() => downloadFile(brandAssets, "opencode-brand-assets.zip")}
|
onClick={() => downloadFile(brandAssets, "opencode-brand-assets.zip")}
|
||||||
>
|
>
|
||||||
Download all assets
|
Download all assets
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -88,13 +84,7 @@ export default function Brand() {
|
|||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button onClick={() => downloadFile(logoLightPng, "opencode-logo-light.png")}>
|
<button onClick={() => downloadFile(logoLightPng, "opencode-logo-light.png")}>
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -105,13 +95,7 @@ export default function Brand() {
|
|||||||
</button>
|
</button>
|
||||||
<button onClick={() => downloadFile(logoLightSvg, "opencode-logo-light.svg")}>
|
<button onClick={() => downloadFile(logoLightSvg, "opencode-logo-light.svg")}>
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -127,13 +111,7 @@ export default function Brand() {
|
|||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button onClick={() => downloadFile(logoDarkPng, "opencode-logo-dark.png")}>
|
<button onClick={() => downloadFile(logoDarkPng, "opencode-logo-dark.png")}>
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -144,13 +122,7 @@ export default function Brand() {
|
|||||||
</button>
|
</button>
|
||||||
<button onClick={() => downloadFile(logoDarkSvg, "opencode-logo-dark.svg")}>
|
<button onClick={() => downloadFile(logoDarkSvg, "opencode-logo-dark.svg")}>
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -164,17 +136,9 @@ export default function Brand() {
|
|||||||
<div>
|
<div>
|
||||||
<img src={previewWordmarkLight} alt="OpenCode brand guidelines" />
|
<img src={previewWordmarkLight} alt="OpenCode brand guidelines" />
|
||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkLightPng, "opencode-wordmark-light.png")}>
|
||||||
onClick={() => downloadFile(wordmarkLightPng, "opencode-wordmark-light.png")}
|
|
||||||
>
|
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -183,17 +147,9 @@ export default function Brand() {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkLightSvg, "opencode-wordmark-light.svg")}>
|
||||||
onClick={() => downloadFile(wordmarkLightSvg, "opencode-wordmark-light.svg")}
|
|
||||||
>
|
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -207,17 +163,9 @@ export default function Brand() {
|
|||||||
<div>
|
<div>
|
||||||
<img src={previewWordmarkDark} alt="OpenCode brand guidelines" />
|
<img src={previewWordmarkDark} alt="OpenCode brand guidelines" />
|
||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkDarkPng, "opencode-wordmark-dark.png")}>
|
||||||
onClick={() => downloadFile(wordmarkDarkPng, "opencode-wordmark-dark.png")}
|
|
||||||
>
|
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -226,17 +174,9 @@ export default function Brand() {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkDarkSvg, "opencode-wordmark-dark.svg")}>
|
||||||
onClick={() => downloadFile(wordmarkDarkSvg, "opencode-wordmark-dark.svg")}
|
|
||||||
>
|
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -250,19 +190,9 @@ export default function Brand() {
|
|||||||
<div>
|
<div>
|
||||||
<img src={previewWordmarkSimpleLight} alt="OpenCode brand guidelines" />
|
<img src={previewWordmarkSimpleLight} alt="OpenCode brand guidelines" />
|
||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkSimpleLightPng, "opencode-wordmark-simple-light.png")}>
|
||||||
onClick={() =>
|
|
||||||
downloadFile(wordmarkSimpleLightPng, "opencode-wordmark-simple-light.png")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -271,19 +201,9 @@ export default function Brand() {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkSimpleLightSvg, "opencode-wordmark-simple-light.svg")}>
|
||||||
onClick={() =>
|
|
||||||
downloadFile(wordmarkSimpleLightSvg, "opencode-wordmark-simple-light.svg")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -297,19 +217,9 @@ export default function Brand() {
|
|||||||
<div>
|
<div>
|
||||||
<img src={previewWordmarkSimpleDark} alt="OpenCode brand guidelines" />
|
<img src={previewWordmarkSimpleDark} alt="OpenCode brand guidelines" />
|
||||||
<div data-component="actions">
|
<div data-component="actions">
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkSimpleDarkPng, "opencode-wordmark-simple-dark.png")}>
|
||||||
onClick={() =>
|
|
||||||
downloadFile(wordmarkSimpleDarkPng, "opencode-wordmark-simple-dark.png")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
PNG
|
PNG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -318,19 +228,9 @@ export default function Brand() {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={() => downloadFile(wordmarkSimpleDarkSvg, "opencode-wordmark-simple-dark.svg")}>
|
||||||
onClick={() =>
|
|
||||||
downloadFile(wordmarkSimpleDarkSvg, "opencode-wordmark-simple-dark.svg")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
SVG
|
SVG
|
||||||
<svg
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
d="M13.9583 10.6247L10 14.583L6.04167 10.6247M10 2.08301V13.958M16.25 17.9163H3.75"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { redirect } from "@solidjs/router"
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
return redirect("https://discord.gg/h5TNnkFVNy")
|
||||||
|
}
|
||||||
@@ -287,7 +287,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-component="enterprise-column-1"] {
|
[data-component="enterprise-column-1"] {
|
||||||
h2 {
|
h1 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--color-text-strong);
|
color: var(--color-text-strong);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import "./index.css"
|
import "./index.css"
|
||||||
import { Title, Meta } from "@solidjs/meta"
|
import { Title, Meta, Link } from "@solidjs/meta"
|
||||||
import { createSignal, Show } from "solid-js"
|
import { createSignal, Show } from "solid-js"
|
||||||
|
import { config } from "~/config"
|
||||||
import { Header } from "~/component/header"
|
import { Header } from "~/component/header"
|
||||||
import { Footer } from "~/component/footer"
|
import { Footer } from "~/component/footer"
|
||||||
import { Legal } from "~/component/legal"
|
import { Legal } from "~/component/legal"
|
||||||
@@ -54,6 +55,7 @@ export default function Enterprise() {
|
|||||||
return (
|
return (
|
||||||
<main data-page="enterprise">
|
<main data-page="enterprise">
|
||||||
<Title>OpenCode | Enterprise solutions for your organisation</Title>
|
<Title>OpenCode | Enterprise solutions for your organisation</Title>
|
||||||
|
<Link rel="canonical" href={`${config.baseUrl}/enterprise`} />
|
||||||
<Meta name="description" content="Contact OpenCode for enterprise solutions" />
|
<Meta name="description" content="Contact OpenCode for enterprise solutions" />
|
||||||
<div data-component="container">
|
<div data-component="container">
|
||||||
<Header />
|
<Header />
|
||||||
@@ -62,41 +64,28 @@ export default function Enterprise() {
|
|||||||
<section data-component="enterprise-content">
|
<section data-component="enterprise-content">
|
||||||
<div data-component="enterprise-columns">
|
<div data-component="enterprise-columns">
|
||||||
<div data-component="enterprise-column-1">
|
<div data-component="enterprise-column-1">
|
||||||
<h2>Your code is yours</h2>
|
<h1>Your code is yours</h1>
|
||||||
<p>
|
<p>
|
||||||
OpenCode operates securely inside your organization with no data or context stored
|
OpenCode operates securely inside your organization with no data or context stored and no licensing
|
||||||
and no licensing restrictions or ownership claims. Start a trial with your team,
|
restrictions or ownership claims. Start a trial with your team, then deploy it across your
|
||||||
then deploy it across your organization by integrating it with your SSO and
|
organization by integrating it with your SSO and internal AI gateway.
|
||||||
internal AI gateway.
|
|
||||||
</p>
|
</p>
|
||||||
<p>Let us know and how we can help.</p>
|
<p>Let us know and how we can help.</p>
|
||||||
|
|
||||||
<Show when={false}>
|
<Show when={false}>
|
||||||
<div data-component="testimonial">
|
<div data-component="testimonial">
|
||||||
<div data-component="quotation">
|
<div data-component="quotation">
|
||||||
<svg
|
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="20"
|
|
||||||
height="17"
|
|
||||||
viewBox="0 0 20 17"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M19.4118 0L16.5882 9.20833H20V17H12.2353V10.0938L16 0H19.4118ZM7.17647 0L4.35294 9.20833H7.76471V17H0V10.0938L3.76471 0H7.17647Z"
|
d="M19.4118 0L16.5882 9.20833H20V17H12.2353V10.0938L16 0H19.4118ZM7.17647 0L4.35294 9.20833H7.76471V17H0V10.0938L3.76471 0H7.17647Z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
Thanks to OpenCode, we found a way to create software to track all our assets —
|
Thanks to OpenCode, we found a way to create software to track all our assets — even the imaginary
|
||||||
even the imaginary ones.
|
ones.
|
||||||
<div data-component="testimonial-logo">
|
<div data-component="testimonial-logo">
|
||||||
<svg
|
<svg width="80" height="79" viewBox="0 0 80 79" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="80"
|
|
||||||
height="79"
|
|
||||||
viewBox="0 0 80 79"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
@@ -213,11 +202,7 @@ export default function Enterprise() {
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{showSuccess() && (
|
{showSuccess() && <div data-component="success-message">Message sent, we'll be in touch soon.</div>}
|
||||||
<div data-component="success-message">
|
|
||||||
Message sent, we'll be in touch soon.
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -230,31 +215,29 @@ export default function Enterprise() {
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="What is OpenCode Enterprise?">
|
<Faq question="What is OpenCode Enterprise?">
|
||||||
OpenCode Enterprise is for organizations that want to ensure that their code and
|
OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves
|
||||||
data never leaves their infrastructure. It can do this by using a centralized
|
their infrastructure. It can do this by using a centralized config that integrates with your SSO and
|
||||||
config that integrates with your SSO and internal AI gateway.
|
internal AI gateway.
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="How do I get started with OpenCode Enterprise?">
|
<Faq question="How do I get started with OpenCode Enterprise?">
|
||||||
Simply start with an internal trial with your team. OpenCode by default does not
|
Simply start with an internal trial with your team. OpenCode by default does not store your code or
|
||||||
store your code or context data, making it easy to get started. Then contact us to
|
context data, making it easy to get started. Then contact us to discuss pricing and implementation
|
||||||
discuss pricing and implementation options.
|
options.
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="How does enterprise pricing work?">
|
<Faq question="How does enterprise pricing work?">
|
||||||
We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not
|
We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not charge for tokens
|
||||||
charge for tokens used. For further details, contact us for a custom quote based
|
used. For further details, contact us for a custom quote based on your organization's needs.
|
||||||
on your organization's needs.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="Is my data secure with OpenCode Enterprise?">
|
<Faq question="Is my data secure with OpenCode Enterprise?">
|
||||||
Yes. OpenCode does not store your code or context data. All processing happens
|
Yes. OpenCode does not store your code or context data. All processing happens locally or through
|
||||||
locally or through direct API calls to your AI provider. With central config and
|
direct API calls to your AI provider. With central config and SSO integration, your data remains
|
||||||
SSO integration, your data remains secure within your organization's
|
secure within your organization's infrastructure.
|
||||||
infrastructure.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ body {
|
|||||||
border-bottom: 1px solid var(--color-border-weak);
|
border-bottom: 1px solid var(--color-border-weak);
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: var(--color-text-strong);
|
color: var(--color-text-strong);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -41,8 +41,7 @@ export async function POST(input: APIEvent) {
|
|||||||
}
|
}
|
||||||
if (body.type === "checkout.session.completed") {
|
if (body.type === "checkout.session.completed") {
|
||||||
const workspaceID = body.data.object.metadata?.workspaceID
|
const workspaceID = body.data.object.metadata?.workspaceID
|
||||||
const amountInCents =
|
const amountInCents = body.data.object.metadata?.amount && parseInt(body.data.object.metadata?.amount)
|
||||||
body.data.object.metadata?.amount && parseInt(body.data.object.metadata?.amount)
|
|
||||||
const customerID = body.data.object.customer as string
|
const customerID = body.data.object.customer as string
|
||||||
const paymentID = body.data.object.payment_intent as string
|
const paymentID = body.data.object.payment_intent as string
|
||||||
const invoiceID = body.data.object.invoice as string
|
const invoiceID = body.data.object.invoice as string
|
||||||
@@ -55,8 +54,7 @@ export async function POST(input: APIEvent) {
|
|||||||
|
|
||||||
await Actor.provide("system", { workspaceID }, async () => {
|
await Actor.provide("system", { workspaceID }, async () => {
|
||||||
const customer = await Billing.get()
|
const customer = await Billing.get()
|
||||||
if (customer?.customerID && customer.customerID !== customerID)
|
if (customer?.customerID && customer.customerID !== customerID) throw new Error("Customer ID mismatch")
|
||||||
throw new Error("Customer ID mismatch")
|
|
||||||
|
|
||||||
// set customer metadata
|
// set customer metadata
|
||||||
if (!customer?.customerID) {
|
if (!customer?.customerID) {
|
||||||
@@ -72,8 +70,7 @@ export async function POST(input: APIEvent) {
|
|||||||
expand: ["payment_method"],
|
expand: ["payment_method"],
|
||||||
})
|
})
|
||||||
const paymentMethod = paymentIntent.payment_method
|
const paymentMethod = paymentIntent.payment_method
|
||||||
if (!paymentMethod || typeof paymentMethod === "string")
|
if (!paymentMethod || typeof paymentMethod === "string") throw new Error("Payment method not expanded")
|
||||||
throw new Error("Payment method not expanded")
|
|
||||||
|
|
||||||
await Database.transaction(async (tx) => {
|
await Database.transaction(async (tx) => {
|
||||||
await tx
|
await tx
|
||||||
@@ -128,12 +125,7 @@ export async function POST(input: APIEvent) {
|
|||||||
amount: PaymentTable.amount,
|
amount: PaymentTable.amount,
|
||||||
})
|
})
|
||||||
.from(PaymentTable)
|
.from(PaymentTable)
|
||||||
.where(
|
.where(and(eq(PaymentTable.paymentID, paymentIntentID), eq(PaymentTable.workspaceID, workspaceID)))
|
||||||
and(
|
|
||||||
eq(PaymentTable.paymentID, paymentIntentID),
|
|
||||||
eq(PaymentTable.workspaceID, workspaceID),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.then((rows) => rows[0]?.amount),
|
.then((rows) => rows[0]?.amount),
|
||||||
)
|
)
|
||||||
if (!amount) throw new Error("Payment not found")
|
if (!amount) throw new Error("Payment not found")
|
||||||
@@ -144,12 +136,7 @@ export async function POST(input: APIEvent) {
|
|||||||
.set({
|
.set({
|
||||||
timeRefunded: new Date(body.created * 1000),
|
timeRefunded: new Date(body.created * 1000),
|
||||||
})
|
})
|
||||||
.where(
|
.where(and(eq(PaymentTable.paymentID, paymentIntentID), eq(PaymentTable.workspaceID, workspaceID)))
|
||||||
and(
|
|
||||||
eq(PaymentTable.paymentID, paymentIntentID),
|
|
||||||
eq(PaymentTable.workspaceID, workspaceID),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
await tx
|
await tx
|
||||||
.update(BillingTable)
|
.update(BillingTable)
|
||||||
|
|||||||
@@ -79,19 +79,17 @@ export default function Home() {
|
|||||||
<strong>LSP enabled</strong> Automatically loads the right LSPs for the LLM
|
<strong>LSP enabled</strong> Automatically loads the right LSPs for the LLM
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>opencode zen</strong> A <a href="/docs/zen">curated list of models</a>{" "}
|
<strong>opencode zen</strong> A <a href="/docs/zen">curated list of models</a> provided by opencode{" "}
|
||||||
provided by opencode <label>New</label>
|
<label>New</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Multi-session</strong> Start multiple agents in parallel on the same project
|
<strong>Multi-session</strong> Start multiple agents in parallel on the same project
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Shareable links</strong> Share a link to any sessions for reference or to
|
<strong>Shareable links</strong> Share a link to any sessions for reference or to debug
|
||||||
debug
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Claude Pro</strong> Log in with Anthropic to use your Claude Pro or Max
|
<strong>Claude Pro</strong> Log in with Anthropic to use your Claude Pro or Max account
|
||||||
account
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Use any model</strong> Supports 75+ LLM providers through{" "}
|
<strong>Use any model</strong> Supports 75+ LLM providers through{" "}
|
||||||
|
|||||||
@@ -85,10 +85,7 @@ export function WorkspacePicker() {
|
|||||||
<Dropdown trigger={currentWorkspace()} align="left">
|
<Dropdown trigger={currentWorkspace()} align="left">
|
||||||
<For each={workspaces()}>
|
<For each={workspaces()}>
|
||||||
{(workspace) => (
|
{(workspace) => (
|
||||||
<DropdownItem
|
<DropdownItem selected={workspace.id === params.id} onClick={() => handleSelectWorkspace(workspace.id)}>
|
||||||
selected={workspace.id === params.id}
|
|
||||||
onClick={() => handleSelectWorkspace(workspace.id)}
|
|
||||||
>
|
|
||||||
{workspace.name || workspace.slug}
|
{workspace.name || workspace.slug}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
)}
|
)}
|
||||||
@@ -98,11 +95,7 @@ export function WorkspacePicker() {
|
|||||||
</button>
|
</button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
||||||
<Modal
|
<Modal open={store.showForm} onClose={() => setStore("showForm", false)} title="Create New Workspace">
|
||||||
open={store.showForm}
|
|
||||||
onClose={() => setStore("showForm", false)}
|
|
||||||
title="Create New Workspace"
|
|
||||||
>
|
|
||||||
<form data-slot="create-form" action={createWorkspace} method="post">
|
<form data-slot="create-form" action={createWorkspace} method="post">
|
||||||
<div data-slot="create-input-group">
|
<div data-slot="create-input-group">
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const getUserEmail = query(async (workspaceID: string) => {
|
|||||||
|
|
||||||
export default function WorkspaceLayout(props: RouteSectionProps) {
|
export default function WorkspaceLayout(props: RouteSectionProps) {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const userEmail = createAsync(() => getUserEmail(params.id))
|
const userEmail = createAsync(() => getUserEmail(params.id!))
|
||||||
return (
|
return (
|
||||||
<main data-page="workspace">
|
<main data-page="workspace">
|
||||||
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import "./[id].css"
|
|||||||
|
|
||||||
export default function WorkspaceLayout(props: RouteSectionProps) {
|
export default function WorkspaceLayout(props: RouteSectionProps) {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const userInfo = createAsync(() => querySessionInfo(params.id))
|
const userInfo = createAsync(() => querySessionInfo(params.id!))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main data-page="workspace">
|
<main data-page="workspace">
|
||||||
|
|||||||
@@ -27,24 +27,31 @@ const createSessionUrl = action(async (workspaceID: string, returnUrl: string) =
|
|||||||
export function BillingSection() {
|
export function BillingSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
// ORIGINAL CODE - COMMENTED OUT FOR TESTING
|
// ORIGINAL CODE - COMMENTED OUT FOR TESTING
|
||||||
const billingInfo = createAsync(() => queryBillingInfo(params.id))
|
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
|
||||||
const checkoutAction = useAction(createCheckoutUrl)
|
const checkoutAction = useAction(createCheckoutUrl)
|
||||||
const checkoutSubmission = useSubmission(createCheckoutUrl)
|
const checkoutSubmission = useSubmission(createCheckoutUrl)
|
||||||
const sessionAction = useAction(createSessionUrl)
|
const sessionAction = useAction(createSessionUrl)
|
||||||
const sessionSubmission = useSubmission(createSessionUrl)
|
const sessionSubmission = useSubmission(createSessionUrl)
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
showAddBalanceForm: false,
|
showAddBalanceForm: false,
|
||||||
addBalanceAmount: "",
|
addBalanceAmount: billingInfo()?.reloadAmount.toString() ?? "",
|
||||||
checkoutRedirecting: false,
|
checkoutRedirecting: false,
|
||||||
sessionRedirecting: false,
|
sessionRedirecting: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const info = billingInfo()
|
||||||
|
if (info) {
|
||||||
|
setStore("addBalanceAmount", info.reloadAmount.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
const balance = createMemo(() => formatBalance(billingInfo()?.balance ?? 0))
|
const balance = createMemo(() => formatBalance(billingInfo()?.balance ?? 0))
|
||||||
|
|
||||||
async function onClickCheckout() {
|
async function onClickCheckout() {
|
||||||
const amount = parseInt(store.addBalanceAmount)
|
const amount = parseInt(store.addBalanceAmount)
|
||||||
const baseUrl = window.location.href
|
const baseUrl = window.location.href
|
||||||
|
|
||||||
const checkout = await checkoutAction(params.id, amount, baseUrl, baseUrl)
|
const checkout = await checkoutAction(params.id!, amount, baseUrl, baseUrl)
|
||||||
if (checkout && checkout.data) {
|
if (checkout && checkout.data) {
|
||||||
setStore("checkoutRedirecting", true)
|
setStore("checkoutRedirecting", true)
|
||||||
window.location.href = checkout.data
|
window.location.href = checkout.data
|
||||||
@@ -53,7 +60,7 @@ export function BillingSection() {
|
|||||||
|
|
||||||
async function onClickSession() {
|
async function onClickSession() {
|
||||||
const baseUrl = window.location.href
|
const baseUrl = window.location.href
|
||||||
const sessionUrl = await sessionAction(params.id, baseUrl)
|
const sessionUrl = await sessionAction(params.id!, baseUrl)
|
||||||
if (sessionUrl && sessionUrl.data) {
|
if (sessionUrl && sessionUrl.data) {
|
||||||
setStore("sessionRedirecting", true)
|
setStore("sessionRedirecting", true)
|
||||||
window.location.href = sessionUrl.data
|
window.location.href = sessionUrl.data
|
||||||
@@ -67,7 +74,6 @@ export function BillingSection() {
|
|||||||
}
|
}
|
||||||
setStore({
|
setStore({
|
||||||
showAddBalanceForm: true,
|
showAddBalanceForm: true,
|
||||||
addBalanceAmount: billingInfo()!.reloadAmount.toString(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +139,7 @@ export function BillingSection() {
|
|||||||
<div data-slot="section-title">
|
<div data-slot="section-title">
|
||||||
<h2>Billing</h2>
|
<h2>Billing</h2>
|
||||||
<p>
|
<p>
|
||||||
Manage payments methods. <a href="mailto:contact@anoma.ly">Contact us</a> if you have any
|
Manage payments methods. <a href="mailto:contact@anoma.ly">Contact us</a> if you have any questions.
|
||||||
questions.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div data-slot="section-content">
|
<div data-slot="section-content">
|
||||||
@@ -164,32 +169,20 @@ export function BillingSection() {
|
|||||||
placeholder="Enter amount"
|
placeholder="Enter amount"
|
||||||
/>
|
/>
|
||||||
<div data-slot="form-actions">
|
<div data-slot="form-actions">
|
||||||
<button
|
<button data-color="ghost" type="button" onClick={() => hideAddBalanceForm()}>
|
||||||
data-color="ghost"
|
|
||||||
type="button"
|
|
||||||
onClick={() => hideAddBalanceForm()}
|
|
||||||
>
|
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
data-color="primary"
|
data-color="primary"
|
||||||
type="button"
|
type="button"
|
||||||
disabled={
|
disabled={!store.addBalanceAmount || checkoutSubmission.pending || store.checkoutRedirecting}
|
||||||
!store.addBalanceAmount ||
|
|
||||||
checkoutSubmission.pending ||
|
|
||||||
store.checkoutRedirecting
|
|
||||||
}
|
|
||||||
onClick={onClickCheckout}
|
onClick={onClickCheckout}
|
||||||
>
|
>
|
||||||
{checkoutSubmission.pending || store.checkoutRedirecting
|
{checkoutSubmission.pending || store.checkoutRedirecting ? "Loading..." : "Add"}
|
||||||
? "Loading..."
|
|
||||||
: "Add"}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Show
|
<Show when={checkoutSubmission.result && (checkoutSubmission.result as any).error}>
|
||||||
when={checkoutSubmission.result && (checkoutSubmission.result as any).error}
|
|
||||||
>
|
|
||||||
{(err: any) => <div data-slot="form-error">{err()}</div>}
|
{(err: any) => <div data-slot="form-error">{err()}</div>}
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
@@ -210,10 +203,7 @@ export function BillingSection() {
|
|||||||
<div data-slot="card-details">
|
<div data-slot="card-details">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={billingInfo()?.paymentMethodType === "card"}>
|
<Match when={billingInfo()?.paymentMethodType === "card"}>
|
||||||
<Show
|
<Show when={billingInfo()?.paymentMethodLast4} fallback={<span data-slot="number">----</span>}>
|
||||||
when={billingInfo()?.paymentMethodLast4}
|
|
||||||
fallback={<span data-slot="number">----</span>}
|
|
||||||
>
|
|
||||||
<span data-slot="secret">••••</span>
|
<span data-slot="secret">••••</span>
|
||||||
<span data-slot="number">{billingInfo()?.paymentMethodLast4}</span>
|
<span data-slot="number">{billingInfo()?.paymentMethodLast4}</span>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -241,9 +231,7 @@ export function BillingSection() {
|
|||||||
disabled={checkoutSubmission.pending || store.checkoutRedirecting}
|
disabled={checkoutSubmission.pending || store.checkoutRedirecting}
|
||||||
onClick={onClickCheckout}
|
onClick={onClickCheckout}
|
||||||
>
|
>
|
||||||
{checkoutSubmission.pending || store.checkoutRedirecting
|
{checkoutSubmission.pending || store.checkoutRedirecting ? "Loading..." : "Enable Billing"}
|
||||||
? "Loading..."
|
|
||||||
: "Enable Billing"}
|
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { queryBillingInfo, querySessionInfo } from "../../common"
|
|||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const userInfo = createAsync(() => querySessionInfo(params.id))
|
const userInfo = createAsync(() => querySessionInfo(params.id!))
|
||||||
const billingInfo = createAsync(() => queryBillingInfo(params.id))
|
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-page="workspace-[id]">
|
<div data-page="workspace-[id]">
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function MonthlyLimitSection() {
|
|||||||
const params = useParams()
|
const params = useParams()
|
||||||
const submission = useSubmission(setMonthlyLimit)
|
const submission = useSubmission(setMonthlyLimit)
|
||||||
const [store, setStore] = createStore({ show: false })
|
const [store, setStore] = createStore({ show: false })
|
||||||
const billingInfo = createAsync(() => queryBillingInfo(params.id))
|
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
|
||||||
|
|
||||||
let input: HTMLInputElement
|
let input: HTMLInputElement
|
||||||
|
|
||||||
@@ -104,13 +104,9 @@ export function MonthlyLimitSection() {
|
|||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<Show
|
<Show when={billingInfo()?.monthlyLimit} fallback={<p data-slot="usage-status">No usage limit set.</p>}>
|
||||||
when={billingInfo()?.monthlyLimit}
|
|
||||||
fallback={<p data-slot="usage-status">No usage limit set.</p>}
|
|
||||||
>
|
|
||||||
<p data-slot="usage-status">
|
<p data-slot="usage-status">
|
||||||
Current usage for{" "}
|
Current usage for {new Date().toLocaleDateString("en-US", { month: "long", timeZone: "UTC" })} is $
|
||||||
{new Date().toLocaleDateString("en-US", { month: "long", timeZone: "UTC" })} is $
|
|
||||||
{(() => {
|
{(() => {
|
||||||
const dateLastUsed = billingInfo()?.timeMonthlyUsageUpdated
|
const dateLastUsed = billingInfo()?.timeMonthlyUsageUpdated
|
||||||
if (!dateLastUsed) return "0"
|
if (!dateLastUsed) return "0"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const downloadReceipt = action(async (workspaceID: string, paymentID: string) =>
|
|||||||
|
|
||||||
export function PaymentSection() {
|
export function PaymentSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const payments = createAsync(() => getPaymentsInfo(params.id))
|
const payments = createAsync(() => getPaymentsInfo(params.id!))
|
||||||
const downloadReceiptAction = useAction(downloadReceipt)
|
const downloadReceiptAction = useAction(downloadReceipt)
|
||||||
|
|
||||||
// DUMMY DATA FOR TESTING
|
// DUMMY DATA FOR TESTING
|
||||||
@@ -89,10 +89,7 @@ export function PaymentSection() {
|
|||||||
<td data-slot="payment-receipt">
|
<td data-slot="payment-receipt">
|
||||||
<button
|
<button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const receiptUrl = await downloadReceiptAction(
|
const receiptUrl = await downloadReceiptAction(params.id!, payment.paymentID!)
|
||||||
params.id,
|
|
||||||
payment.paymentID!,
|
|
||||||
)
|
|
||||||
if (receiptUrl) {
|
if (receiptUrl) {
|
||||||
window.open(receiptUrl, "_blank")
|
window.open(receiptUrl, "_blank")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const setReload = action(async (form: FormData) => {
|
|||||||
|
|
||||||
export function ReloadSection() {
|
export function ReloadSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const billingInfo = createAsync(() => queryBillingInfo(params.id))
|
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
|
||||||
const setReloadSubmission = useSubmission(setReload)
|
const setReloadSubmission = useSubmission(setReload)
|
||||||
const reloadSubmission = useSubmission(reload)
|
const reloadSubmission = useSubmission(reload)
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
@@ -69,11 +69,7 @@ export function ReloadSection() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (
|
if (!setReloadSubmission.pending && setReloadSubmission.result && !(setReloadSubmission.result as any).error) {
|
||||||
!setReloadSubmission.pending &&
|
|
||||||
setReloadSubmission.result &&
|
|
||||||
!(setReloadSubmission.result as any).error
|
|
||||||
) {
|
|
||||||
setStore("show", false)
|
setStore("show", false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -108,8 +104,8 @@ export function ReloadSection() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Auto reload is <b>enabled</b>. We'll reload <b>${billingInfo()?.reloadAmount}</b>{" "}
|
Auto reload is <b>enabled</b>. We'll reload <b>${billingInfo()?.reloadAmount}</b> (+$1.23 processing fee)
|
||||||
(+$1.23 processing fee) when balance reaches <b>${billingInfo()?.reloadTrigger}</b>.
|
when balance reaches <b>${billingInfo()?.reloadTrigger}</b>.
|
||||||
</p>
|
</p>
|
||||||
</Show>
|
</Show>
|
||||||
<button data-color="primary" type="button" onClick={() => show()}>
|
<button data-color="primary" type="button" onClick={() => show()}>
|
||||||
@@ -194,8 +190,8 @@ export function ReloadSection() {
|
|||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
})}
|
})}
|
||||||
. Reason: {billingInfo()?.reloadError?.replace(/\.$/, "")}. Please update your payment
|
. Reason: {billingInfo()?.reloadError?.replace(/\.$/, "")}. Please update your payment method and try
|
||||||
method and try again.
|
again.
|
||||||
</p>
|
</p>
|
||||||
<form action={reload} method="post" data-slot="create-form">
|
<form action={reload} method="post" data-slot="create-form">
|
||||||
<input type="hidden" name="workspaceID" value={params.id} />
|
<input type="hidden" name="workspaceID" value={params.id} />
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
.root {
|
||||||
|
[data-component="empty-state"] {
|
||||||
|
padding: var(--space-20) var(--space-6);
|
||||||
|
text-align: center;
|
||||||
|
border: 1px dashed var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
height: 400px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="filter-container"] {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-3);
|
||||||
|
|
||||||
|
[data-component="dropdown"] {
|
||||||
|
[data-slot="trigger"] {
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
padding: var(--space-2) var(--space-3);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
box-shadow: 0 0 0 3px var(--color-accent-alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="chevron"] {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="dropdown"] {
|
||||||
|
min-width: 200px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: var(--space-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="month-picker"] {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="month-button"] {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: none;
|
||||||
|
border: none !important;
|
||||||
|
color: var(--color-text);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: var(--space-2) var(--space-3);
|
||||||
|
border-radius: var(--border-radius-xs);
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-bg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
display: block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="month-label"] {
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text);
|
||||||
|
line-height: 1.5;
|
||||||
|
min-width: 140px;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="model-item"] {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-2);
|
||||||
|
padding: var(--space-2) var(--space-3);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
color: var(--color-text);
|
||||||
|
border: none !important;
|
||||||
|
background: none;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-bg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
flex: 1;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="chart-container"] {
|
||||||
|
padding: var(--space-6);
|
||||||
|
background: var(--color-bg-secondary);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 40rem) {
|
||||||
|
[data-slot="chart-container"] {
|
||||||
|
height: 300px;
|
||||||
|
padding: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-component="empty-state"] {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,423 @@
|
|||||||
|
import { and, Database, eq, gte, inArray, isNull, lte, or, sql, sum } from "@opencode-ai/console-core/drizzle/index.js"
|
||||||
|
import { UsageTable } from "@opencode-ai/console-core/schema/billing.sql.js"
|
||||||
|
import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
|
||||||
|
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
|
||||||
|
import { AuthTable } from "@opencode-ai/console-core/schema/auth.sql.js"
|
||||||
|
import { createAsync, query, useParams } from "@solidjs/router"
|
||||||
|
import { createEffect, createMemo, onCleanup, Show, For } from "solid-js"
|
||||||
|
import { createStore } from "solid-js/store"
|
||||||
|
import { withActor } from "~/context/auth.withActor"
|
||||||
|
import { Dropdown } from "~/component/dropdown"
|
||||||
|
import { IconChevronLeft, IconChevronRight } from "~/component/icon"
|
||||||
|
import styles from "./graph-section.module.css"
|
||||||
|
import {
|
||||||
|
Chart,
|
||||||
|
BarController,
|
||||||
|
BarElement,
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
Tooltip,
|
||||||
|
Legend,
|
||||||
|
type ChartConfiguration,
|
||||||
|
} from "chart.js"
|
||||||
|
|
||||||
|
Chart.register(BarController, BarElement, CategoryScale, LinearScale, Tooltip, Legend)
|
||||||
|
|
||||||
|
async function getCosts(workspaceID: string, year: number, month: number) {
|
||||||
|
"use server"
|
||||||
|
return withActor(async () => {
|
||||||
|
const startDate = new Date(year, month, 1)
|
||||||
|
const endDate = new Date(year, month + 1, 0)
|
||||||
|
|
||||||
|
// First query: get usage data without joining keys
|
||||||
|
const usageData = await Database.use((tx) =>
|
||||||
|
tx
|
||||||
|
.select({
|
||||||
|
date: sql<string>`DATE(${UsageTable.timeCreated})`,
|
||||||
|
model: UsageTable.model,
|
||||||
|
totalCost: sum(UsageTable.cost),
|
||||||
|
keyId: UsageTable.keyID,
|
||||||
|
})
|
||||||
|
.from(UsageTable)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(UsageTable.workspaceID, workspaceID),
|
||||||
|
gte(UsageTable.timeCreated, startDate),
|
||||||
|
lte(UsageTable.timeCreated, endDate),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.groupBy(sql`DATE(${UsageTable.timeCreated})`, UsageTable.model, UsageTable.keyID)
|
||||||
|
.then((x) =>
|
||||||
|
x.map((r) => ({
|
||||||
|
...r,
|
||||||
|
totalCost: r.totalCost ? parseInt(r.totalCost) : 0,
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get unique key IDs from usage
|
||||||
|
const usageKeyIds = new Set(usageData.map((r) => r.keyId).filter((id) => id !== null))
|
||||||
|
|
||||||
|
// Second query: get all existing keys plus any keys from usage
|
||||||
|
const keysData = await Database.use((tx) =>
|
||||||
|
tx
|
||||||
|
.select({
|
||||||
|
keyId: KeyTable.id,
|
||||||
|
keyName: KeyTable.name,
|
||||||
|
userEmail: AuthTable.subject,
|
||||||
|
timeDeleted: KeyTable.timeDeleted,
|
||||||
|
})
|
||||||
|
.from(KeyTable)
|
||||||
|
.innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID)))
|
||||||
|
.innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(KeyTable.workspaceID, workspaceID),
|
||||||
|
usageKeyIds.size > 0
|
||||||
|
? or(inArray(KeyTable.id, Array.from(usageKeyIds)), isNull(KeyTable.timeDeleted))
|
||||||
|
: isNull(KeyTable.timeDeleted),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.orderBy(AuthTable.subject, KeyTable.name),
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
usage: usageData,
|
||||||
|
keys: keysData.map((key) => ({
|
||||||
|
id: key.keyId,
|
||||||
|
displayName:
|
||||||
|
key.timeDeleted !== null
|
||||||
|
? `${key.userEmail} - ${key.keyName} (deleted)`
|
||||||
|
: `${key.userEmail} - ${key.keyName}`,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}, workspaceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryCosts = query(getCosts, "costs.get")
|
||||||
|
|
||||||
|
const MODEL_COLORS: Record<string, string> = {
|
||||||
|
"claude-sonnet-4-5": "#D4745C",
|
||||||
|
"claude-sonnet-4": "#E8B4A4",
|
||||||
|
"claude-opus-4": "#C8A098",
|
||||||
|
"claude-haiku-4-5": "#F0D8D0",
|
||||||
|
"claude-3-5-haiku": "#F8E8E0",
|
||||||
|
"gpt-5.1": "#4A90E2",
|
||||||
|
"gpt-5.1-codex": "#6BA8F0",
|
||||||
|
"gpt-5": "#7DB8F8",
|
||||||
|
"gpt-5-codex": "#9FCAFF",
|
||||||
|
"gpt-5-nano": "#B8D8FF",
|
||||||
|
"grok-code": "#8B5CF6",
|
||||||
|
"big-pickle": "#10B981",
|
||||||
|
"kimi-k2": "#F59E0B",
|
||||||
|
"qwen3-coder": "#EC4899",
|
||||||
|
"glm-4.6": "#14B8A6",
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModelColor(model: string): string {
|
||||||
|
if (MODEL_COLORS[model]) return MODEL_COLORS[model]
|
||||||
|
|
||||||
|
const hash = model.split("").reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0)
|
||||||
|
const hue = Math.abs(hash) % 360
|
||||||
|
return `hsl(${hue}, 50%, 65%)`
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDateLabel(dateStr: string): string {
|
||||||
|
const date = new Date()
|
||||||
|
const [y, m, d] = dateStr.split("-").map(Number)
|
||||||
|
date.setFullYear(y)
|
||||||
|
date.setMonth(m - 1)
|
||||||
|
date.setDate(d)
|
||||||
|
date.setHours(0, 0, 0, 0)
|
||||||
|
const month = date.toLocaleDateString("en-US", { month: "short" })
|
||||||
|
const day = date.getUTCDate().toString().padStart(2, "0")
|
||||||
|
return `${month} ${day}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOpacityToColor(color: string, opacity: number): string {
|
||||||
|
if (color.startsWith("#")) {
|
||||||
|
const r = parseInt(color.slice(1, 3), 16)
|
||||||
|
const g = parseInt(color.slice(3, 5), 16)
|
||||||
|
const b = parseInt(color.slice(5, 7), 16)
|
||||||
|
return `rgba(${r}, ${g}, ${b}, ${opacity})`
|
||||||
|
}
|
||||||
|
if (color.startsWith("hsl")) return color.replace(")", `, ${opacity})`).replace("hsl", "hsla")
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GraphSection() {
|
||||||
|
let canvasRef: HTMLCanvasElement | undefined
|
||||||
|
let chartInstance: Chart | undefined
|
||||||
|
const params = useParams()
|
||||||
|
const now = new Date()
|
||||||
|
const [store, setStore] = createStore({
|
||||||
|
data: null as Awaited<ReturnType<typeof getCosts>> | null,
|
||||||
|
year: now.getFullYear(),
|
||||||
|
month: now.getMonth(),
|
||||||
|
key: null as string | null,
|
||||||
|
model: null as string | null,
|
||||||
|
modelDropdownOpen: false,
|
||||||
|
keyDropdownOpen: false,
|
||||||
|
})
|
||||||
|
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 })
|
||||||
|
}
|
||||||
|
|
||||||
|
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) })
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getDates = createMemo(() => {
|
||||||
|
const daysInMonth = new Date(store.year, store.month + 1, 0).getDate()
|
||||||
|
return Array.from({ length: daysInMonth }, (_, i) => {
|
||||||
|
const date = new Date(store.year, store.month, i + 1)
|
||||||
|
return date.toISOString().split("T")[0]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const getKeyName = (keyID: string | null): string => {
|
||||||
|
if (!keyID || !store.data?.keys) return "All Keys"
|
||||||
|
const found = store.data.keys.find((k) => k.id === keyID)
|
||||||
|
return found?.displayName ?? "All Keys"
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatMonthYear = () =>
|
||||||
|
new Date(store.year, store.month, 1).toLocaleDateString("en-US", { month: "long", year: "numeric" })
|
||||||
|
|
||||||
|
const isCurrentMonth = () => store.year === now.getFullYear() && store.month === now.getMonth()
|
||||||
|
|
||||||
|
const chartConfig = createMemo((): ChartConfiguration | null => {
|
||||||
|
const data = getData()
|
||||||
|
const dates = getDates()
|
||||||
|
if (!data?.usage?.length) return null
|
||||||
|
|
||||||
|
const dailyData = new Map<string, Map<string, number>>()
|
||||||
|
for (const dateKey of dates) dailyData.set(dateKey, new Map())
|
||||||
|
|
||||||
|
data.usage
|
||||||
|
.filter((row) => (store.key ? row.keyId === store.key : true))
|
||||||
|
.forEach((row) => {
|
||||||
|
const dayMap = dailyData.get(row.date)
|
||||||
|
if (!dayMap) return
|
||||||
|
dayMap.set(row.model, (dayMap.get(row.model) ?? 0) + row.totalCost)
|
||||||
|
})
|
||||||
|
|
||||||
|
const filteredModels = store.model === null ? getModels() : [store.model]
|
||||||
|
|
||||||
|
const datasets = filteredModels.map((model) => {
|
||||||
|
const color = getModelColor(model)
|
||||||
|
return {
|
||||||
|
label: model,
|
||||||
|
data: dates.map((date) => (dailyData.get(date)?.get(model) || 0) / 100_000_000),
|
||||||
|
backgroundColor: color,
|
||||||
|
hoverBackgroundColor: color,
|
||||||
|
borderWidth: 0,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "bar",
|
||||||
|
data: {
|
||||||
|
labels: dates.map(formatDateLabel),
|
||||||
|
datasets,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
stacked: true,
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
maxRotation: 0,
|
||||||
|
autoSkipPadding: 20,
|
||||||
|
color: "rgba(255, 255, 255, 0.5)",
|
||||||
|
font: {
|
||||||
|
family: "monospace",
|
||||||
|
size: 11,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
stacked: true,
|
||||||
|
beginAtZero: true,
|
||||||
|
grid: {
|
||||||
|
color: "rgba(255, 255, 255, 0.1)",
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
color: "rgba(255, 255, 255, 0.5)",
|
||||||
|
font: {
|
||||||
|
family: "monospace",
|
||||||
|
size: 11,
|
||||||
|
},
|
||||||
|
callback: (value) => {
|
||||||
|
const num = Number(value)
|
||||||
|
return num >= 1000 ? `$${(num / 1000).toFixed(1)}k` : `$${num.toFixed(0)}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
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)",
|
||||||
|
borderWidth: 1,
|
||||||
|
padding: 12,
|
||||||
|
displayColors: true,
|
||||||
|
callbacks: {
|
||||||
|
label: (context) => {
|
||||||
|
const value = context.parsed.y
|
||||||
|
if (!value || value === 0) return
|
||||||
|
return `${context.dataset.label}: $${value.toFixed(2)}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
position: "bottom",
|
||||||
|
labels: {
|
||||||
|
color: "rgba(255, 255, 255, 0.7)",
|
||||||
|
font: {
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
|
padding: 16,
|
||||||
|
boxWidth: 16,
|
||||||
|
boxHeight: 16,
|
||||||
|
usePointStyle: false,
|
||||||
|
},
|
||||||
|
onHover: (event, legendItem, legend) => {
|
||||||
|
const chart = legend.chart
|
||||||
|
chart.data.datasets?.forEach((dataset, i) => {
|
||||||
|
const meta = chart.getDatasetMeta(i)
|
||||||
|
const baseColor = getModelColor(dataset.label || "")
|
||||||
|
const color = i === legendItem.datasetIndex ? baseColor : addOpacityToColor(baseColor, 0.3)
|
||||||
|
meta.data.forEach((bar: any) => {
|
||||||
|
bar.options.backgroundColor = color
|
||||||
|
})
|
||||||
|
})
|
||||||
|
chart.update("none")
|
||||||
|
},
|
||||||
|
onLeave: (event, legendItem, legend) => {
|
||||||
|
const chart = legend.chart
|
||||||
|
chart.data.datasets?.forEach((dataset, i) => {
|
||||||
|
const meta = chart.getDatasetMeta(i)
|
||||||
|
const baseColor = getModelColor(dataset.label || "")
|
||||||
|
meta.data.forEach((bar: any) => {
|
||||||
|
bar.options.backgroundColor = baseColor
|
||||||
|
})
|
||||||
|
})
|
||||||
|
chart.update("none")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const config = chartConfig()
|
||||||
|
if (!config || !canvasRef) return
|
||||||
|
|
||||||
|
if (chartInstance) chartInstance.destroy()
|
||||||
|
chartInstance = new Chart(canvasRef, config)
|
||||||
|
})
|
||||||
|
|
||||||
|
onCleanup(() => chartInstance?.destroy())
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section class={styles.root}>
|
||||||
|
<div data-slot="section-title">
|
||||||
|
<h2>Cost</h2>
|
||||||
|
<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>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
<Show
|
||||||
|
when={chartConfig()}
|
||||||
|
fallback={
|
||||||
|
<div data-component="empty-state">
|
||||||
|
<p>No usage data available for the selected period.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div data-slot="chart-container">
|
||||||
|
<canvas ref={canvasRef} />
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -5,13 +5,14 @@ import { NewUserSection } from "./new-user-section"
|
|||||||
import { UsageSection } from "./usage-section"
|
import { UsageSection } from "./usage-section"
|
||||||
import { ModelSection } from "./model-section"
|
import { ModelSection } from "./model-section"
|
||||||
import { ProviderSection } from "./provider-section"
|
import { ProviderSection } from "./provider-section"
|
||||||
|
import { GraphSection } from "./graph-section"
|
||||||
import { IconLogo } from "~/component/icon"
|
import { IconLogo } from "~/component/icon"
|
||||||
import { querySessionInfo, queryBillingInfo, createCheckoutUrl, formatBalance } from "../common"
|
import { querySessionInfo, queryBillingInfo, createCheckoutUrl, formatBalance } from "../common"
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const userInfo = createAsync(() => querySessionInfo(params.id))
|
const userInfo = createAsync(() => querySessionInfo(params.id!))
|
||||||
const billingInfo = createAsync(() => queryBillingInfo(params.id))
|
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
|
||||||
const checkoutAction = useAction(createCheckoutUrl)
|
const checkoutAction = useAction(createCheckoutUrl)
|
||||||
const checkoutSubmission = useSubmission(createCheckoutUrl)
|
const checkoutSubmission = useSubmission(createCheckoutUrl)
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
@@ -21,7 +22,7 @@ export default function () {
|
|||||||
|
|
||||||
async function onClickCheckout() {
|
async function onClickCheckout() {
|
||||||
const baseUrl = window.location.href
|
const baseUrl = window.location.href
|
||||||
const checkout = await checkoutAction(params.id, billingInfo()!.reloadAmount, baseUrl, baseUrl)
|
const checkout = await checkoutAction(params.id!, billingInfo()!.reloadAmount, baseUrl, baseUrl)
|
||||||
if (checkout && checkout.data) {
|
if (checkout && checkout.data) {
|
||||||
setStore("checkoutRedirecting", true)
|
setStore("checkoutRedirecting", true)
|
||||||
window.location.href = checkout.data
|
window.location.href = checkout.data
|
||||||
@@ -51,9 +52,7 @@ export default function () {
|
|||||||
disabled={checkoutSubmission.pending || store.checkoutRedirecting}
|
disabled={checkoutSubmission.pending || store.checkoutRedirecting}
|
||||||
onClick={onClickCheckout}
|
onClick={onClickCheckout}
|
||||||
>
|
>
|
||||||
{checkoutSubmission.pending || store.checkoutRedirecting
|
{checkoutSubmission.pending || store.checkoutRedirecting ? "Loading..." : "Enable billing"}
|
||||||
? "Loading..."
|
|
||||||
: "Enable billing"}
|
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -68,6 +67,9 @@ export default function () {
|
|||||||
|
|
||||||
<div data-slot="sections">
|
<div data-slot="sections">
|
||||||
<NewUserSection />
|
<NewUserSection />
|
||||||
|
<Show when={userInfo()?.isAdmin}>
|
||||||
|
<GraphSection />
|
||||||
|
</Show>
|
||||||
<ModelSection />
|
<ModelSection />
|
||||||
<Show when={userInfo()?.isAdmin}>
|
<Show when={userInfo()?.isAdmin}>
|
||||||
<ProviderSection />
|
<ProviderSection />
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const listKeys = query(async (workspaceID: string) => {
|
|||||||
|
|
||||||
export function KeySection() {
|
export function KeySection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const keys = createAsync(() => listKeys(params.id))
|
const keys = createAsync(() => listKeys(params.id!))
|
||||||
const submission = useSubmission(createKey)
|
const submission = useSubmission(createKey)
|
||||||
const [store, setStore] = createStore({ show: false })
|
const [store, setStore] = createStore({ show: false })
|
||||||
|
|
||||||
@@ -146,20 +146,14 @@ export function KeySection() {
|
|||||||
title="Copy API key"
|
title="Copy API key"
|
||||||
>
|
>
|
||||||
<span>{key.keyDisplay}</span>
|
<span>{key.keyDisplay}</span>
|
||||||
<Show
|
<Show when={copied()} fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}>
|
||||||
when={copied()}
|
|
||||||
fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}
|
|
||||||
>
|
|
||||||
<IconCheck style={{ width: "14px", height: "14px" }} />
|
<IconCheck style={{ width: "14px", height: "14px" }} />
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</td>
|
</td>
|
||||||
<td data-slot="key-user-email">{key.email}</td>
|
<td data-slot="key-user-email">{key.email}</td>
|
||||||
<td
|
<td data-slot="key-last-used" title={key.timeUsed ? formatDateUTC(key.timeUsed) : undefined}>
|
||||||
data-slot="key-last-used"
|
|
||||||
title={key.timeUsed ? formatDateUTC(key.timeUsed) : undefined}
|
|
||||||
>
|
|
||||||
{key.timeUsed ? formatDateForTable(key.timeUsed) : "-"}
|
{key.timeUsed ? formatDateForTable(key.timeUsed) : "-"}
|
||||||
</td>
|
</td>
|
||||||
<td data-slot="key-actions">
|
<td data-slot="key-actions">
|
||||||
|
|||||||
@@ -85,12 +85,7 @@ const updateMember = action(async (form: FormData) => {
|
|||||||
)
|
)
|
||||||
}, "member.update")
|
}, "member.update")
|
||||||
|
|
||||||
function MemberRow(props: {
|
function MemberRow(props: { member: any; workspaceID: string; actorID: string; actorRole: string }) {
|
||||||
member: any
|
|
||||||
workspaceID: string
|
|
||||||
actorID: string
|
|
||||||
actorRole: string
|
|
||||||
}) {
|
|
||||||
const submission = useSubmission(updateMember)
|
const submission = useSubmission(updateMember)
|
||||||
const isCurrentUser = () => props.actorID === props.member.id
|
const isCurrentUser = () => props.actorID === props.member.id
|
||||||
const isAdmin = () => props.actorRole === "admin"
|
const isAdmin = () => props.actorRole === "admin"
|
||||||
@@ -214,7 +209,7 @@ const roleOptions = [
|
|||||||
|
|
||||||
export function MemberSection() {
|
export function MemberSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const data = createAsync(() => listMembers(params.id))
|
const data = createAsync(() => listMembers(params.id!))
|
||||||
const submission = useSubmission(inviteMember)
|
const submission = useSubmission(inviteMember)
|
||||||
const [store, setStore] = createStore({
|
const [store, setStore] = createStore({
|
||||||
show: false,
|
show: false,
|
||||||
@@ -333,7 +328,7 @@ export function MemberSection() {
|
|||||||
{(member) => (
|
{(member) => (
|
||||||
<MemberRow
|
<MemberRow
|
||||||
member={member}
|
member={member}
|
||||||
workspaceID={params.id}
|
workspaceID={params.id!}
|
||||||
actorID={data()!.actorID}
|
actorID={data()!.actorID}
|
||||||
actorRole={data()!.actorRole}
|
actorRole={data()!.actorRole}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { querySessionInfo } from "../common"
|
|||||||
import {
|
import {
|
||||||
IconAlibaba,
|
IconAlibaba,
|
||||||
IconAnthropic,
|
IconAnthropic,
|
||||||
|
IconGoogle,
|
||||||
IconMoonshotAI,
|
IconMoonshotAI,
|
||||||
IconOpenAI,
|
IconOpenAI,
|
||||||
IconStealth,
|
IconStealth,
|
||||||
@@ -18,6 +19,7 @@ import {
|
|||||||
const getModelLab = (modelId: string) => {
|
const getModelLab = (modelId: string) => {
|
||||||
if (modelId.startsWith("claude")) return "Anthropic"
|
if (modelId.startsWith("claude")) return "Anthropic"
|
||||||
if (modelId.startsWith("gpt")) return "OpenAI"
|
if (modelId.startsWith("gpt")) return "OpenAI"
|
||||||
|
if (modelId.startsWith("gemini")) return "Google"
|
||||||
if (modelId.startsWith("kimi")) return "Moonshot AI"
|
if (modelId.startsWith("kimi")) return "Moonshot AI"
|
||||||
if (modelId.startsWith("glm")) return "Z.ai"
|
if (modelId.startsWith("glm")) return "Z.ai"
|
||||||
if (modelId.startsWith("qwen")) return "Alibaba"
|
if (modelId.startsWith("qwen")) return "Alibaba"
|
||||||
@@ -30,9 +32,19 @@ const getModelsInfo = query(async (workspaceID: string) => {
|
|||||||
return withActor(async () => {
|
return withActor(async () => {
|
||||||
return {
|
return {
|
||||||
all: Object.entries(ZenData.list().models)
|
all: Object.entries(ZenData.list().models)
|
||||||
.filter(([id, _model]) => !["claude-3-5-haiku", "minimax-m2"].includes(id))
|
.filter(([id, _model]) => !["claude-3-5-haiku"].includes(id))
|
||||||
.filter(([id, _model]) => !id.startsWith("an-"))
|
.filter(([id, _model]) => !id.startsWith("alpha-"))
|
||||||
.sort(([_idA, modelA], [_idB, modelB]) => modelA.name.localeCompare(modelB.name))
|
.sort(([idA, modelA], [idB, modelB]) => {
|
||||||
|
const priority = ["big-pickle", "grok", "claude", "gpt", "gemini"]
|
||||||
|
const getPriority = (id: string) => {
|
||||||
|
const index = priority.findIndex((p) => id.startsWith(p))
|
||||||
|
return index === -1 ? Infinity : index
|
||||||
|
}
|
||||||
|
const pA = getPriority(idA)
|
||||||
|
const pB = getPriority(idB)
|
||||||
|
if (pA !== pB) return pA - pB
|
||||||
|
return modelA.name.localeCompare(modelB.name)
|
||||||
|
})
|
||||||
.map(([id, model]) => ({ id, name: model.name })),
|
.map(([id, model]) => ({ id, name: model.name })),
|
||||||
disabled: await Model.listDisabled(),
|
disabled: await Model.listDisabled(),
|
||||||
}
|
}
|
||||||
@@ -60,8 +72,8 @@ const updateModel = action(async (form: FormData) => {
|
|||||||
|
|
||||||
export function ModelSection() {
|
export function ModelSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const modelsInfo = createAsync(() => getModelsInfo(params.id))
|
const modelsInfo = createAsync(() => getModelsInfo(params.id!))
|
||||||
const userInfo = createAsync(() => querySessionInfo(params.id))
|
const userInfo = createAsync(() => querySessionInfo(params.id!))
|
||||||
|
|
||||||
const modelsWithLab = createMemo(() => {
|
const modelsWithLab = createMemo(() => {
|
||||||
const info = modelsInfo()
|
const info = modelsInfo()
|
||||||
@@ -76,8 +88,7 @@ export function ModelSection() {
|
|||||||
<div data-slot="section-title">
|
<div data-slot="section-title">
|
||||||
<h2>Models</h2>
|
<h2>Models</h2>
|
||||||
<p>
|
<p>
|
||||||
Manage which models workspace members can access.{" "}
|
Manage which models workspace members can access. <a href="/docs/zen#pricing ">Learn more</a>.
|
||||||
<a href="/docs/zen#pricing ">Learn more</a>.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div data-slot="models-list">
|
<div data-slot="models-list">
|
||||||
@@ -105,6 +116,8 @@ export function ModelSection() {
|
|||||||
return <IconOpenAI width={16} height={16} />
|
return <IconOpenAI width={16} height={16} />
|
||||||
case "Anthropic":
|
case "Anthropic":
|
||||||
return <IconAnthropic width={16} height={16} />
|
return <IconAnthropic width={16} height={16} />
|
||||||
|
case "Google":
|
||||||
|
return <IconGoogle width={16} height={16} />
|
||||||
case "Moonshot AI":
|
case "Moonshot AI":
|
||||||
return <IconMoonshotAI width={16} height={16} />
|
return <IconMoonshotAI width={16} height={16} />
|
||||||
case "Z.ai":
|
case "Z.ai":
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const listKeys = query(async (workspaceID: string) => {
|
|||||||
export function NewUserSection() {
|
export function NewUserSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const [copiedKey, setCopiedKey] = createSignal(false)
|
const [copiedKey, setCopiedKey] = createSignal(false)
|
||||||
const keys = createAsync(() => listKeys(params.id))
|
const keys = createAsync(() => listKeys(params.id!))
|
||||||
const usage = createAsync(() => getUsageInfo(params.id))
|
const usage = createAsync(() => getUsageInfo(params.id!))
|
||||||
const isNew = createMemo(() => {
|
const isNew = createMemo(() => {
|
||||||
const keysList = keys()
|
const keysList = keys()
|
||||||
const usageList = usage()
|
const usageList = usage()
|
||||||
@@ -43,24 +43,15 @@ export function NewUserSection() {
|
|||||||
<div data-component="feature-grid">
|
<div data-component="feature-grid">
|
||||||
<div data-slot="feature">
|
<div data-slot="feature">
|
||||||
<h3>Tested & Verified Models</h3>
|
<h3>Tested & Verified Models</h3>
|
||||||
<p>
|
<p>We've benchmarked and tested models specifically for coding agents to ensure the best performance.</p>
|
||||||
We've benchmarked and tested models specifically for coding agents to ensure the best
|
|
||||||
performance.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div data-slot="feature">
|
<div data-slot="feature">
|
||||||
<h3>Highest Quality</h3>
|
<h3>Highest Quality</h3>
|
||||||
<p>
|
<p>Access models configured for optimal performance - no downgrades or routing to cheaper providers.</p>
|
||||||
Access models configured for optimal performance - no downgrades or routing to cheaper
|
|
||||||
providers.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div data-slot="feature">
|
<div data-slot="feature">
|
||||||
<h3>No Lock-in</h3>
|
<h3>No Lock-in</h3>
|
||||||
<p>
|
<p>Use Zen with any coding agent, and continue using other providers with opencode whenever you want.</p>
|
||||||
Use Zen with any coding agent, and continue using other providers with opencode
|
|
||||||
whenever you want.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -54,11 +54,8 @@ const listProviders = query(async (workspaceID: string) => {
|
|||||||
|
|
||||||
function ProviderRow(props: { provider: Provider }) {
|
function ProviderRow(props: { provider: Provider }) {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const providers = createAsync(() => listProviders(params.id))
|
const providers = createAsync(() => listProviders(params.id!))
|
||||||
const saveSubmission = useSubmission(
|
const saveSubmission = useSubmission(saveProvider, ([fd]) => fd.get("provider")?.toString() === props.provider.key)
|
||||||
saveProvider,
|
|
||||||
([fd]) => fd.get("provider")?.toString() === props.provider.key,
|
|
||||||
)
|
|
||||||
const removeSubmission = useSubmission(
|
const removeSubmission = useSubmission(
|
||||||
removeProvider,
|
removeProvider,
|
||||||
([fd]) => fd.get("provider")?.toString() === props.provider.key,
|
([fd]) => fd.get("provider")?.toString() === props.provider.key,
|
||||||
@@ -94,16 +91,9 @@ function ProviderRow(props: { provider: Provider }) {
|
|||||||
<td data-slot="provider-key">
|
<td data-slot="provider-key">
|
||||||
<Show
|
<Show
|
||||||
when={store.editing}
|
when={store.editing}
|
||||||
fallback={
|
fallback={<span>{providerData() ? maskCredentials(providerData()!.credentials) : "-"}</span>}
|
||||||
<span>{providerData() ? maskCredentials(providerData()!.credentials) : "-"}</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
id={`provider-form-${props.provider.key}`}
|
|
||||||
action={saveProvider}
|
|
||||||
method="post"
|
|
||||||
data-slot="edit-form"
|
|
||||||
>
|
>
|
||||||
|
<form id={`provider-form-${props.provider.key}`} action={saveProvider} method="post" data-slot="edit-form">
|
||||||
<div data-slot="input-wrapper">
|
<div data-slot="input-wrapper">
|
||||||
<input
|
<input
|
||||||
ref={(r) => (input = r)}
|
ref={(r) => (input = r)}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const updateWorkspace = action(async (form: FormData) => {
|
|||||||
|
|
||||||
export function SettingsSection() {
|
export function SettingsSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const workspaceInfo = createAsync(() => getWorkspaceInfo(params.id))
|
const workspaceInfo = createAsync(() => getWorkspaceInfo(params.id!))
|
||||||
const submission = useSubmission(updateWorkspace)
|
const submission = useSubmission(updateWorkspace)
|
||||||
const [store, setStore] = createStore({ show: false })
|
const [store, setStore] = createStore({ show: false })
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
.root {
|
.root {
|
||||||
|
/* Empty state */
|
||||||
[data-component="empty-state"] {
|
[data-component="empty-state"] {
|
||||||
padding: var(--space-20) var(--space-6);
|
padding: var(--space-20) var(--space-6);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px dashed var(--color-border);
|
border: 1px dashed var(--color-border);
|
||||||
border-radius: var(--border-radius-sm);
|
border-radius: var(--border-radius-sm);
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--space-2);
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
line-height: 1.5;
|
|
||||||
font-size: var(--font-size-sm);
|
font-size: var(--font-size-sm);
|
||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Table container */
|
||||||
[data-slot="usage-table"] {
|
[data-slot="usage-table"] {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Table element */
|
||||||
[data-slot="usage-table-element"] {
|
[data-slot="usage-table-element"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
@@ -48,7 +47,6 @@
|
|||||||
|
|
||||||
&[data-slot="usage-model"] {
|
&[data-slot="usage-model"] {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-weight: 400;
|
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
@@ -56,33 +54,133 @@
|
|||||||
|
|
||||||
&[data-slot="usage-cost"] {
|
&[data-slot="usage-cost"] {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="tokens-with-breakdown"] {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="breakdown-button"] {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.15s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr {
|
[data-slot="breakdown-popup"] {
|
||||||
&:last-child td {
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 100%;
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
background: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
padding: var(--space-2);
|
||||||
|
z-index: 10;
|
||||||
|
min-width: 180px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:last-child td {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pagination */
|
||||||
|
[data-slot="pagination"] {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: var(--space-2);
|
||||||
|
padding: var(--space-4) 0;
|
||||||
|
border-top: 1px solid var(--color-border-muted);
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: var(--space-2) var(--space-4);
|
||||||
|
background: var(--color-bg-secondary);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: var(--color-bg-tertiary);
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile responsive */
|
||||||
@media (max-width: 40rem) {
|
@media (max-width: 40rem) {
|
||||||
|
[data-slot="usage-table-element"] {
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
padding: var(--space-2) var(--space-3);
|
padding: var(--space-2) var(--space-3);
|
||||||
font-size: var(--font-size-xs);
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
/* Hide Model column on mobile */
|
||||||
&:nth-child(2) /* Model */ {
|
th:nth-child(2),
|
||||||
|
td:nth-child(2) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
td {
|
/* Breakdown popup content */
|
||||||
&:nth-child(2) /* Model */ {
|
[data-slot="breakdown-row"] {
|
||||||
display: none;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-4);
|
||||||
|
padding: var(--space-1) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-slot="breakdown-label"] {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
[data-slot="breakdown-value"] {
|
||||||
|
color: var(--color-text);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,69 @@
|
|||||||
import { Billing } from "@opencode-ai/console-core/billing.js"
|
import { Billing } from "@opencode-ai/console-core/billing.js"
|
||||||
import { query, useParams, createAsync } from "@solidjs/router"
|
import { createAsync, query, useParams } from "@solidjs/router"
|
||||||
import { createMemo, For, Show } from "solid-js"
|
import { createMemo, For, Show, createEffect, createSignal } from "solid-js"
|
||||||
import { formatDateUTC, formatDateForTable } from "../common"
|
import { formatDateUTC, formatDateForTable } from "../common"
|
||||||
import { withActor } from "~/context/auth.withActor"
|
import { withActor } from "~/context/auth.withActor"
|
||||||
|
import { IconChevronLeft, IconChevronRight, IconBreakdown } from "~/component/icon"
|
||||||
import styles from "./usage-section.module.css"
|
import styles from "./usage-section.module.css"
|
||||||
|
import { createStore } from "solid-js/store"
|
||||||
|
|
||||||
const getUsageInfo = query(async (workspaceID: string) => {
|
const PAGE_SIZE = 50
|
||||||
|
|
||||||
|
async function getUsageInfo(workspaceID: string, page: number) {
|
||||||
"use server"
|
"use server"
|
||||||
return withActor(async () => {
|
return withActor(async () => {
|
||||||
return await Billing.usages()
|
return await Billing.usages(page, PAGE_SIZE)
|
||||||
}, workspaceID)
|
}, workspaceID)
|
||||||
}, "usage.list")
|
}
|
||||||
|
|
||||||
|
const queryUsageInfo = query(getUsageInfo, "usage.list")
|
||||||
|
|
||||||
export function UsageSection() {
|
export function UsageSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
// ORIGINAL CODE - COMMENTED OUT FOR TESTING
|
const usage = createAsync(() => queryUsageInfo(params.id!, 0))
|
||||||
const usage = createAsync(() => getUsageInfo(params.id))
|
const [store, setStore] = createStore({ page: 0, usage: [] as Awaited<ReturnType<typeof getUsageInfo>> })
|
||||||
|
const [openBreakdownId, setOpenBreakdownId] = createSignal<string | null>(null)
|
||||||
|
|
||||||
// DUMMY DATA FOR TESTING
|
createEffect(() => {
|
||||||
// const usage = () => [
|
setStore({ usage: usage() })
|
||||||
// {
|
}, [usage])
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 0).toISOString(), // Today
|
|
||||||
// model: "claude-3-5-sonnet-20241022",
|
createEffect(() => {
|
||||||
// inputTokens: 1247,
|
if (!openBreakdownId()) return
|
||||||
// outputTokens: 423,
|
|
||||||
// cost: 125400000, // $1.254
|
const handleClickOutside = (e: MouseEvent) => {
|
||||||
// },
|
const target = e.target as HTMLElement
|
||||||
// {
|
if (!target.closest('[data-slot="tokens-with-breakdown"]')) {
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 0.5).toISOString(), // 12 hours ago
|
setOpenBreakdownId(null)
|
||||||
// model: "claude-3-haiku-20240307",
|
}
|
||||||
// inputTokens: 892,
|
}
|
||||||
// outputTokens: 156,
|
|
||||||
// cost: 23500000, // $0.235
|
document.addEventListener("click", handleClickOutside)
|
||||||
// },
|
return () => document.removeEventListener("click", handleClickOutside)
|
||||||
// {
|
})
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 1).toISOString(), // Yesterday
|
|
||||||
// model: "claude-3-5-sonnet-20241022",
|
const hasResults = createMemo(() => store.usage && store.usage.length > 0)
|
||||||
// inputTokens: 2134,
|
const canGoPrev = createMemo(() => store.page > 0)
|
||||||
// outputTokens: 687,
|
const canGoNext = createMemo(() => store.usage && store.usage.length === PAGE_SIZE)
|
||||||
// cost: 234700000, // $2.347
|
|
||||||
// },
|
const calculateTotalInputTokens = (u: Awaited<ReturnType<typeof getUsageInfo>>[0]) => {
|
||||||
// {
|
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWrite5mTokens ?? 0) + (u.cacheWrite1hTokens ?? 0)
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 1.3).toISOString(), // 1.3 days ago
|
}
|
||||||
// model: "gpt-4o-mini",
|
|
||||||
// inputTokens: 567,
|
const goPrev = async () => {
|
||||||
// outputTokens: 234,
|
const usage = await getUsageInfo(params.id!, store.page - 1)
|
||||||
// cost: 8900000, // $0.089
|
setStore({
|
||||||
// },
|
page: store.page - 1,
|
||||||
// {
|
usage,
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 2).toISOString(), // 2 days ago
|
})
|
||||||
// model: "claude-3-opus-20240229",
|
}
|
||||||
// inputTokens: 1893,
|
const goNext = async () => {
|
||||||
// outputTokens: 945,
|
const usage = await getUsageInfo(params.id!, store.page + 1)
|
||||||
// cost: 445600000, // $4.456
|
setStore({
|
||||||
// },
|
page: store.page + 1,
|
||||||
// {
|
usage,
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 2.7).toISOString(), // 2.7 days ago
|
})
|
||||||
// model: "gpt-4o",
|
}
|
||||||
// inputTokens: 1456,
|
|
||||||
// outputTokens: 532,
|
|
||||||
// cost: 156800000, // $1.568
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 3).toISOString(), // 3 days ago
|
|
||||||
// model: "claude-3-haiku-20240307",
|
|
||||||
// inputTokens: 634,
|
|
||||||
// outputTokens: 89,
|
|
||||||
// cost: 12300000, // $0.123
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// timeCreated: new Date(Date.now() - 86400000 * 4).toISOString(), // 4 days ago
|
|
||||||
// model: "claude-3-5-sonnet-20241022",
|
|
||||||
// inputTokens: 3245,
|
|
||||||
// outputTokens: 1123,
|
|
||||||
// cost: 387200000, // $3.872
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section class={styles.root}>
|
<section class={styles.root}>
|
||||||
@@ -85,7 +73,7 @@ export function UsageSection() {
|
|||||||
</div>
|
</div>
|
||||||
<div data-slot="usage-table">
|
<div data-slot="usage-table">
|
||||||
<Show
|
<Show
|
||||||
when={usage() && usage()!.length > 0}
|
when={hasResults()}
|
||||||
fallback={
|
fallback={
|
||||||
<div data-component="empty-state">
|
<div data-component="empty-state">
|
||||||
<p>Make your first API call to get started.</p>
|
<p>Make your first API call to get started.</p>
|
||||||
@@ -103,16 +91,51 @@ export function UsageSection() {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<For each={usage()!}>
|
<For each={store.usage}>
|
||||||
{(usage) => {
|
{(usage, index) => {
|
||||||
const date = createMemo(() => new Date(usage.timeCreated))
|
const date = createMemo(() => new Date(usage.timeCreated))
|
||||||
|
const totalInputTokens = createMemo(() => calculateTotalInputTokens(usage))
|
||||||
|
const breakdownId = `breakdown-${index()}`
|
||||||
|
const isOpen = createMemo(() => openBreakdownId() === breakdownId)
|
||||||
|
const isClaude = usage.model.toLowerCase().includes("claude")
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td data-slot="usage-date" title={formatDateUTC(date())}>
|
<td data-slot="usage-date" title={formatDateUTC(date())}>
|
||||||
{formatDateForTable(date())}
|
{formatDateForTable(date())}
|
||||||
</td>
|
</td>
|
||||||
<td data-slot="usage-model">{usage.model}</td>
|
<td data-slot="usage-model">{usage.model}</td>
|
||||||
<td data-slot="usage-tokens">{usage.inputTokens}</td>
|
<td data-slot="usage-tokens">
|
||||||
|
<div data-slot="tokens-with-breakdown" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<button
|
||||||
|
data-slot="breakdown-button"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setOpenBreakdownId(isOpen() ? null : breakdownId)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconBreakdown />
|
||||||
|
</button>
|
||||||
|
<span onClick={() => setOpenBreakdownId(null)}>{totalInputTokens()}</span>
|
||||||
|
<Show when={isOpen()}>
|
||||||
|
<div data-slot="breakdown-popup" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<div data-slot="breakdown-row">
|
||||||
|
<span data-slot="breakdown-label">Input</span>
|
||||||
|
<span data-slot="breakdown-value">{usage.inputTokens}</span>
|
||||||
|
</div>
|
||||||
|
<div data-slot="breakdown-row">
|
||||||
|
<span data-slot="breakdown-label">Cache Read</span>
|
||||||
|
<span data-slot="breakdown-value">{usage.cacheReadTokens ?? 0}</span>
|
||||||
|
</div>
|
||||||
|
<Show when={isClaude}>
|
||||||
|
<div data-slot="breakdown-row">
|
||||||
|
<span data-slot="breakdown-label">Cache Write</span>
|
||||||
|
<span data-slot="breakdown-value">{usage.cacheWrite5mTokens ?? 0}</span>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td data-slot="usage-tokens">{usage.outputTokens}</td>
|
<td data-slot="usage-tokens">{usage.outputTokens}</td>
|
||||||
<td data-slot="usage-cost">${((usage.cost ?? 0) / 100000000).toFixed(4)}</td>
|
<td data-slot="usage-cost">${((usage.cost ?? 0) / 100000000).toFixed(4)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -121,6 +144,16 @@ export function UsageSection() {
|
|||||||
</For>
|
</For>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<Show when={canGoPrev() || canGoNext()}>
|
||||||
|
<div data-slot="pagination">
|
||||||
|
<button disabled={!canGoPrev()} onClick={goPrev}>
|
||||||
|
<IconChevronLeft />
|
||||||
|
</button>
|
||||||
|
<button disabled={!canGoNext()} onClick={goNext}>
|
||||||
|
<IconChevronRight />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -67,10 +67,7 @@ export const querySessionInfo = query(async (workspaceID: string) => {
|
|||||||
return withActor(() => {
|
return withActor(() => {
|
||||||
return {
|
return {
|
||||||
isAdmin: Actor.userRole() === "admin",
|
isAdmin: Actor.userRole() === "admin",
|
||||||
isBeta:
|
isBeta: Resource.App.stage === "production" ? workspaceID === "wrk_01K46JDFR0E75SG2Q8K172KF3Y" : true,
|
||||||
Resource.App.stage === "production"
|
|
||||||
? workspaceID === "wrk_01K46JDFR0E75SG2Q8K172KF3Y"
|
|
||||||
: true,
|
|
||||||
}
|
}
|
||||||
}, workspaceID)
|
}, workspaceID)
|
||||||
}, "session.get")
|
}, "session.get")
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ body {
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: var(--color-text-strong);
|
color: var(--color-text-strong);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createAsync, query, redirect } from "@solidjs/router"
|
|||||||
import { Title, Meta, Link } from "@solidjs/meta"
|
import { Title, Meta, Link } from "@solidjs/meta"
|
||||||
import { HttpHeader } from "@solidjs/start"
|
import { HttpHeader } from "@solidjs/start"
|
||||||
import zenLogoLight from "../../asset/zen-ornate-light.svg"
|
import zenLogoLight from "../../asset/zen-ornate-light.svg"
|
||||||
|
import { config } from "~/config"
|
||||||
import zenLogoDark from "../../asset/zen-ornate-dark.svg"
|
import zenLogoDark from "../../asset/zen-ornate-dark.svg"
|
||||||
import compareVideo from "../../asset/lander/opencode-comparison-min.mp4"
|
import compareVideo from "../../asset/lander/opencode-comparison-min.mp4"
|
||||||
import compareVideoPoster from "../../asset/lander/opencode-comparison-poster.png"
|
import compareVideoPoster from "../../asset/lander/opencode-comparison-poster.png"
|
||||||
@@ -28,11 +29,9 @@ export default function Home() {
|
|||||||
createAsync(() => checkLoggedIn())
|
createAsync(() => checkLoggedIn())
|
||||||
return (
|
return (
|
||||||
<main data-page="zen">
|
<main data-page="zen">
|
||||||
<HttpHeader
|
<HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" />
|
||||||
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>
|
<Title>OpenCode Zen | A curated set of reliable optimized models for coding agents</Title>
|
||||||
|
<Link rel="canonical" href={`${config.baseUrl}/zen`} />
|
||||||
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
<Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" />
|
||||||
<Meta property="og:image" content="/social-share-zen.png" />
|
<Meta property="og:image" content="/social-share-zen.png" />
|
||||||
<Meta name="twitter:image" content="/social-share-zen.png" />
|
<Meta name="twitter:image" content="/social-share-zen.png" />
|
||||||
@@ -45,21 +44,15 @@ export default function Home() {
|
|||||||
<div data-slot="hero-copy">
|
<div data-slot="hero-copy">
|
||||||
<img data-slot="zen logo light" src={zenLogoLight} alt="zen logo light" />
|
<img data-slot="zen logo light" src={zenLogoLight} alt="zen logo light" />
|
||||||
<img data-slot="zen logo dark" src={zenLogoDark} alt="zen logo dark" />
|
<img data-slot="zen logo dark" src={zenLogoDark} alt="zen logo dark" />
|
||||||
<strong>Reliable optimized models for coding agents</strong>
|
<h1>Reliable optimized models for coding agents</h1>
|
||||||
<p>
|
<p>
|
||||||
Zen gives you access to a curated set of AI models that OpenCode has tested and
|
Zen gives you access to a curated set of AI models that OpenCode has tested and benchmarked specifically
|
||||||
benchmarked specifically for coding agents. No need to worry about inconsistent
|
for coding agents. No need to worry about inconsistent performance and quality, use validated models
|
||||||
performance and quality, use validated models that work.
|
that work.
|
||||||
</p>
|
</p>
|
||||||
<div data-slot="model-logos">
|
<div data-slot="model-logos">
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<mask
|
<mask
|
||||||
id="mask0_79_128586"
|
id="mask0_79_128586"
|
||||||
style="mask-type:luminance"
|
style="mask-type:luminance"
|
||||||
@@ -80,17 +73,8 @@ export default function Home() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
<path d="M13.7891 3.93164L20.2223 20.0677H23.7502L17.317 3.93164H13.7891Z" fill="currentColor" />
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M13.7891 3.93164L20.2223 20.0677H23.7502L17.317 3.93164H13.7891Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
<path
|
||||||
d="M6.32538 13.6824L8.52662 8.01177L10.7279 13.6824H6.32538ZM6.68225 3.93164L0.25 20.0677H3.84652L5.16202 16.6791H11.8914L13.2067 20.0677H16.8033L10.371 3.93164H6.68225Z"
|
d="M6.32538 13.6824L8.52662 8.01177L10.7279 13.6824H6.32538ZM6.68225 3.93164L0.25 20.0677H3.84652L5.16202 16.6791H11.8914L13.2067 20.0677H16.8033L10.371 3.93164H6.68225Z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
@@ -98,13 +82,7 @@ export default function Home() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M9.16861 16.0529L17.2018 9.85156C17.5957 9.54755 18.1586 9.66612 18.3463 10.1384C19.3339 12.6288 18.8926 15.6217 16.9276 17.6766C14.9626 19.7314 12.2285 20.1821 9.72948 19.1557L6.9995 20.4775C10.9151 23.2763 15.6699 22.5841 18.6411 19.4749C20.9979 17.0103 21.7278 13.6508 21.0453 10.6214L21.0515 10.6278C20.0617 6.17736 21.2948 4.39847 23.8207 0.760904C23.8804 0.674655 23.9402 0.588405 24 0.5L20.6762 3.97585V3.96506L9.16658 16.0551"
|
d="M9.16861 16.0529L17.2018 9.85156C17.5957 9.54755 18.1586 9.66612 18.3463 10.1384C19.3339 12.6288 18.8926 15.6217 16.9276 17.6766C14.9626 19.7314 12.2285 20.1821 9.72948 19.1557L6.9995 20.4775C10.9151 23.2763 15.6699 22.5841 18.6411 19.4749C20.9979 17.0103 21.7278 13.6508 21.0453 10.6214L21.0515 10.6278C20.0617 6.17736 21.2948 4.39847 23.8207 0.760904C23.8804 0.674655 23.9402 0.588405 24 0.5L20.6762 3.97585V3.96506L9.16658 16.0551"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
@@ -116,13 +94,7 @@ export default function Home() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
@@ -132,13 +104,7 @@ export default function Home() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M12.6241 11.346L20.3848 3.44816C20.5309 3.29931 20.4487 3 20.2601 3H16.0842C16.0388 3 15.9949 3.01897 15.9594 3.05541L7.59764 11.5629C7.46721 11.6944 7.27446 11.5771 7.27446 11.3666V3.25183C7.27446 3.11242 7.18515 3 7.07594 3H4.19843C4.08932 3 4 3.11242 4 3.25183V20.7482C4 20.8876 4.08932 21 4.19843 21H7.07594C7.18515 21 7.27446 20.8876 7.27446 20.7482V17.1834C7.27446 17.1073 7.30136 17.0344 7.34815 16.987L9.94075 14.3486C10.0031 14.2853 10.0895 14.2757 10.159 14.3232L17.0934 19.5573C18.2289 20.3412 19.4975 20.8226 20.786 20.9652C20.9008 20.9778 21 20.8606 21 20.7133V17.3559C21 17.2276 20.9249 17.1232 20.8243 17.1073C20.0659 16.9853 19.326 16.6845 18.6569 16.222L12.6538 11.764C12.5291 11.6785 12.5135 11.4584 12.6241 11.346Z"
|
d="M12.6241 11.346L20.3848 3.44816C20.5309 3.29931 20.4487 3 20.2601 3H16.0842C16.0388 3 15.9949 3.01897 15.9594 3.05541L7.59764 11.5629C7.46721 11.6944 7.27446 11.5771 7.27446 11.3666V3.25183C7.27446 3.11242 7.18515 3 7.07594 3H4.19843C4.08932 3 4 3.11242 4 3.25183V20.7482C4 20.8876 4.08932 21 4.19843 21H7.07594C7.18515 21 7.27446 20.8876 7.27446 20.7482V17.1834C7.27446 17.1073 7.30136 17.0344 7.34815 16.987L9.94075 14.3486C10.0031 14.2853 10.0895 14.2757 10.159 14.3232L17.0934 19.5573C18.2289 20.3412 19.4975 20.8226 20.786 20.9652C20.9008 20.9778 21 20.8606 21 20.7133V17.3559C21 17.2276 20.9249 17.1232 20.8243 17.1073C20.0659 16.9853 19.326 16.6845 18.6569 16.222L12.6538 11.764C12.5291 11.6785 12.5135 11.4584 12.6241 11.346Z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
@@ -148,13 +114,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<a href="/auth">
|
<a href="/auth">
|
||||||
<span>Get started with Zen </span>
|
<span>Get started with Zen </span>
|
||||||
<svg
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
|
d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
@@ -166,23 +126,14 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
<div data-slot="pricing-copy">
|
<div data-slot="pricing-copy">
|
||||||
<p>
|
<p>
|
||||||
<strong>Add $20 Pay as you go balance</strong>{" "}
|
<strong>Add $20 Pay as you go balance</strong> <span>(+$1.23 card processing fee)</span>
|
||||||
<span>(+$1.23 card processing fee)</span>
|
|
||||||
</p>
|
</p>
|
||||||
<p>Use with any agent. Set monthly spend limits. Cancel any time.</p>
|
<p>Use with any agent. Set monthly spend limits. Cancel any time.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section data-component="comparison">
|
<section data-component="comparison">
|
||||||
<video
|
<video src={compareVideo} autoplay playsinline loop muted preload="auto" poster={compareVideoPoster}>
|
||||||
src={compareVideo}
|
|
||||||
autoplay
|
|
||||||
playsinline
|
|
||||||
loop
|
|
||||||
muted
|
|
||||||
preload="auto"
|
|
||||||
poster={compareVideoPoster}
|
|
||||||
>
|
|
||||||
Your browser does not support the video tag.
|
Your browser does not support the video tag.
|
||||||
</video>
|
</video>
|
||||||
</section>
|
</section>
|
||||||
@@ -191,8 +142,8 @@ export default function Home() {
|
|||||||
<div data-slot="section-title">
|
<div data-slot="section-title">
|
||||||
<h3>What problem is Zen solving?</h3>
|
<h3>What problem is Zen solving?</h3>
|
||||||
<p>
|
<p>
|
||||||
There are so many models available, but only a few work well with coding agents.
|
There are so many models available, but only a few work well with coding agents. Most providers
|
||||||
Most providers configure them differently with varying results.
|
configure them differently with varying results.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p>We're fixing this for everyone, not just OpenCode users.</p>
|
<p>We're fixing this for everyone, not just OpenCode users.</p>
|
||||||
@@ -227,15 +178,14 @@ export default function Home() {
|
|||||||
<li>
|
<li>
|
||||||
<span>[2]</span>
|
<span>[2]</span>
|
||||||
<div>
|
<div>
|
||||||
<strong>Use Zen with transparent pricing</strong> -{" "}
|
<strong>Use Zen with transparent pricing</strong> - <a href="/docs/zen/#pricing">pay per request</a>{" "}
|
||||||
<a href="/docs/zen/#pricing">pay per request</a> with zero markups
|
with zero markups
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span>[3]</span>
|
<span>[3]</span>
|
||||||
<div>
|
<div>
|
||||||
<strong>Auto-top up</strong> - when your balance reaches $5 we’ll automatically
|
<strong>Auto-top up</strong> - when your balance reaches $5 we’ll automatically add $20
|
||||||
add $20
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -247,9 +197,8 @@ export default function Home() {
|
|||||||
<div>
|
<div>
|
||||||
<span>[*]</span>
|
<span>[*]</span>
|
||||||
<p>
|
<p>
|
||||||
All Zen models are hosted in the US. Providers follow a zero-retention policy and
|
All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data
|
||||||
do not use your data for model training, with the{" "}
|
for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>.
|
||||||
<a href="/docs/zen/#privacy">following exceptions</a>.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -304,8 +253,7 @@ export default function Home() {
|
|||||||
<span>ex-Head of Design, Laravel</span>
|
<span>ex-Head of Design, Laravel</span>
|
||||||
</div>
|
</div>
|
||||||
<div data-slot="quote">
|
<div data-slot="quote">
|
||||||
With <span>@OpenCode</span> Zen I know all the models are tested and perfect for
|
With <span>@OpenCode</span> Zen I know all the models are tested and perfect for coding agents.
|
||||||
coding agents.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@@ -329,44 +277,38 @@ export default function Home() {
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="What is OpenCode Zen?">
|
<Faq question="What is OpenCode Zen?">
|
||||||
Zen is a curated set of AI models tested and benchmarked for coding agents created
|
Zen is a curated set of AI models tested and benchmarked for coding agents created by the team behind
|
||||||
by the team behind OpenCode.
|
OpenCode.
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="What makes Zen more accurate?">
|
<Faq question="What makes Zen more accurate?">
|
||||||
Zen only provides models that have been specifically tested and benchmarked for
|
Zen only provides models that have been specifically tested and benchmarked for coding agents. You
|
||||||
coding agents. You wouldn’t use a butter knife to cut steak, don’t use poor models
|
wouldn’t use a butter knife to cut steak, don’t use poor models for coding.
|
||||||
for coding.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="Is Zen cheaper?">
|
<Faq question="Is Zen cheaper?">
|
||||||
Zen is not for profit. Zen passes through the costs from the model providers to
|
Zen is not for profit. Zen passes through the costs from the model providers to you. The higher Zen’s
|
||||||
you. The higher Zen’s usage the more OpenCode can negotiate better rates and pass
|
usage the more OpenCode can negotiate better rates and pass those to you.
|
||||||
those to you.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="How much does Zen cost?">
|
<Faq question="How much does Zen cost?">
|
||||||
Zen <a href="/docs/zen/#pricing">charges per request</a> with zero markups, so you
|
Zen <a href="/docs/zen/#pricing">charges per request</a> with zero markups, so you pay exactly what
|
||||||
pay exactly what the model provider charges. Your total cost depends on usage, and
|
the model provider charges. Your total cost depends on usage, and you can set monthly spend limits in
|
||||||
you can set monthly spend limits in your <a href="/auth">account</a>. To cover
|
your <a href="/auth">account</a>. To cover costs, OpenCode adds only a small payment processing fee of
|
||||||
costs, OpenCode adds only a small payment processing fee of $1.23 per $20 balance
|
$1.23 per $20 balance top-up.
|
||||||
top-up.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="What about data and privacy?">
|
<Faq question="What about data and privacy?">
|
||||||
All Zen models are hosted in the US. Providers follow a zero-retention policy and
|
All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data
|
||||||
do not use your data for model training, with the{" "}
|
for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>.
|
||||||
<a href="/docs/zen/#privacy">following exceptions</a>.
|
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="Can I set spend limits?">
|
<Faq question="Can I set spend limits?">Yes, you can set monthly spending limits in your account.</Faq>
|
||||||
Yes, you can set monthly spending limits in your account.
|
|
||||||
</Faq>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="Can I cancel?">
|
<Faq question="Can I cancel?">
|
||||||
@@ -375,8 +317,8 @@ export default function Home() {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Faq question="Can I use Zen with other coding agents?">
|
<Faq question="Can I use Zen with other coding agents?">
|
||||||
While Zen works great with OpenCode, you can use Zen with any agent. Follow the
|
While Zen works great with OpenCode, you can use Zen with any agent. Follow the setup instructions in
|
||||||
setup instructions in your preferred coding agent.
|
your preferred coding agent.
|
||||||
</Faq>
|
</Faq>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ export class CreditsError extends Error {}
|
|||||||
export class MonthlyLimitError extends Error {}
|
export class MonthlyLimitError extends Error {}
|
||||||
export class UserLimitError extends Error {}
|
export class UserLimitError extends Error {}
|
||||||
export class ModelError extends Error {}
|
export class ModelError extends Error {}
|
||||||
|
export class RateLimitError extends Error {}
|
||||||
|
|||||||
@@ -12,54 +12,65 @@ import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
|
|||||||
import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
|
import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
|
||||||
import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
|
import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
|
||||||
import { logger } from "./logger"
|
import { logger } from "./logger"
|
||||||
import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError } from "./error"
|
import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError, RateLimitError } from "./error"
|
||||||
import {
|
import { createBodyConverter, createStreamPartConverter, createResponseConverter } from "./provider/provider"
|
||||||
createBodyConverter,
|
|
||||||
createStreamPartConverter,
|
|
||||||
createResponseConverter,
|
|
||||||
} from "./provider/provider"
|
|
||||||
import { anthropicHelper } from "./provider/anthropic"
|
import { anthropicHelper } from "./provider/anthropic"
|
||||||
|
import { googleHelper } from "./provider/google"
|
||||||
import { openaiHelper } from "./provider/openai"
|
import { openaiHelper } from "./provider/openai"
|
||||||
import { oaCompatHelper } from "./provider/openai-compatible"
|
import { oaCompatHelper } from "./provider/openai-compatible"
|
||||||
|
import { createRateLimiter } from "./rateLimiter"
|
||||||
|
|
||||||
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
||||||
type Model = ZenData["models"][string]
|
type RetryOptions = {
|
||||||
|
excludeProviders: string[]
|
||||||
|
retryCount: number
|
||||||
|
}
|
||||||
|
|
||||||
export async function handler(
|
export async function handler(
|
||||||
input: APIEvent,
|
input: APIEvent,
|
||||||
opts: {
|
opts: {
|
||||||
format: ZenData.Format
|
format: ZenData.Format
|
||||||
parseApiKey: (headers: Headers) => string | undefined
|
parseApiKey: (headers: Headers) => string | undefined
|
||||||
|
parseModel: (url: string, body: any) => string
|
||||||
|
parseIsStream: (url: string, body: any) => boolean
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
type AuthInfo = Awaited<ReturnType<typeof authenticate>>
|
||||||
|
type ModelInfo = Awaited<ReturnType<typeof validateModel>>
|
||||||
|
type ProviderInfo = Awaited<ReturnType<typeof selectProvider>>
|
||||||
|
|
||||||
|
const MAX_RETRIES = 3
|
||||||
const FREE_WORKSPACES = [
|
const FREE_WORKSPACES = [
|
||||||
"wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank
|
"wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank
|
||||||
"wrk_01K6W1A3VE0KMNVSCQT43BG2SX", // opencode bench
|
"wrk_01K6W1A3VE0KMNVSCQT43BG2SX", // opencode bench
|
||||||
]
|
]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const url = input.request.url
|
||||||
const body = await input.request.json()
|
const body = await input.request.json()
|
||||||
|
const ip = input.request.headers.get("x-real-ip") ?? ""
|
||||||
|
const model = opts.parseModel(url, body)
|
||||||
|
const isStream = opts.parseIsStream(url, body)
|
||||||
logger.metric({
|
logger.metric({
|
||||||
is_tream: !!body.stream,
|
is_tream: isStream,
|
||||||
session: input.request.headers.get("x-opencode-session"),
|
session: input.request.headers.get("x-opencode-session"),
|
||||||
request: input.request.headers.get("x-opencode-request"),
|
request: input.request.headers.get("x-opencode-request"),
|
||||||
})
|
})
|
||||||
const zenData = ZenData.list()
|
const zenData = ZenData.list()
|
||||||
const modelInfo = validateModel(zenData, body.model)
|
const modelInfo = validateModel(zenData, model)
|
||||||
const providerInfo = selectProvider(
|
const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip)
|
||||||
zenData,
|
await rateLimiter?.check()
|
||||||
modelInfo,
|
|
||||||
input.request.headers.get("x-real-ip") ?? "",
|
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, providerInfo)
|
||||||
validateBilling(modelInfo, authInfo)
|
validateBilling(authInfo, modelInfo)
|
||||||
validateModelSettings(authInfo)
|
validateModelSettings(authInfo)
|
||||||
updateProviderKey(authInfo, providerInfo)
|
updateProviderKey(authInfo, providerInfo)
|
||||||
logger.metric({ provider: providerInfo.id })
|
logger.metric({ provider: providerInfo.id })
|
||||||
|
|
||||||
// Request to model provider
|
|
||||||
const startTimestamp = Date.now()
|
const startTimestamp = Date.now()
|
||||||
const reqUrl = providerInfo.modifyUrl(providerInfo.api)
|
const reqUrl = providerInfo.modifyUrl(providerInfo.api, providerInfo.model, isStream)
|
||||||
const reqBody = JSON.stringify(
|
const reqBody = JSON.stringify(
|
||||||
providerInfo.modifyBody({
|
providerInfo.modifyBody({
|
||||||
...createBodyConverter(opts.format, providerInfo.format)(body),
|
...createBodyConverter(opts.format, providerInfo.format)(body),
|
||||||
@@ -67,22 +78,37 @@ export async function handler(
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
logger.debug("REQUEST URL: " + reqUrl)
|
logger.debug("REQUEST URL: " + reqUrl)
|
||||||
logger.debug("REQUEST: " + reqBody)
|
logger.debug("REQUEST: " + reqBody.substring(0, 300) + "...")
|
||||||
const res = await fetch(reqUrl, {
|
const res = await fetch(reqUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: (() => {
|
headers: (() => {
|
||||||
const headers = input.request.headers
|
const headers = new Headers(input.request.headers)
|
||||||
headers.delete("host")
|
|
||||||
headers.delete("content-length")
|
|
||||||
providerInfo.modifyHeaders(headers, body, providerInfo.apiKey)
|
providerInfo.modifyHeaders(headers, body, providerInfo.apiKey)
|
||||||
Object.entries(providerInfo.headerMappings ?? {}).forEach(([k, v]) => {
|
Object.entries(providerInfo.headerMappings ?? {}).forEach(([k, v]) => {
|
||||||
headers.set(k, headers.get(v)!)
|
headers.set(k, headers.get(v)!)
|
||||||
})
|
})
|
||||||
|
headers.delete("host")
|
||||||
|
headers.delete("content-length")
|
||||||
|
headers.delete("x-opencode-request")
|
||||||
|
headers.delete("x-opencode-session")
|
||||||
return headers
|
return headers
|
||||||
})(),
|
})(),
|
||||||
body: reqBody,
|
body: reqBody,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Try another provider => stop retrying if using fallback provider
|
||||||
|
if (res.status !== 200 && modelInfo.fallbackProvider && providerInfo.id !== modelInfo.fallbackProvider) {
|
||||||
|
return retriableRequest({
|
||||||
|
excludeProviders: [...retry.excludeProviders, providerInfo.id],
|
||||||
|
retryCount: retry.retryCount + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { providerInfo, authInfo, res, startTimestamp }
|
||||||
|
}
|
||||||
|
|
||||||
|
const { providerInfo, authInfo, res, startTimestamp } = await retriableRequest()
|
||||||
|
|
||||||
// Scrub response headers
|
// Scrub response headers
|
||||||
const resHeaders = new Headers()
|
const resHeaders = new Headers()
|
||||||
const keepHeaders = ["content-type", "cache-control"]
|
const keepHeaders = ["content-type", "cache-control"]
|
||||||
@@ -92,17 +118,15 @@ export async function handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("STATUS: " + res.status + " " + res.statusText)
|
logger.debug("STATUS: " + res.status + " " + res.statusText)
|
||||||
if (res.status === 400 || res.status === 503) {
|
|
||||||
logger.debug("RESPONSE: " + (await res.text()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle non-streaming response
|
// Handle non-streaming response
|
||||||
if (!body.stream) {
|
if (!isStream) {
|
||||||
const responseConverter = createResponseConverter(providerInfo.format, opts.format)
|
const responseConverter = createResponseConverter(providerInfo.format, opts.format)
|
||||||
const json = await res.json()
|
const json = await res.json()
|
||||||
const body = JSON.stringify(responseConverter(json))
|
const body = JSON.stringify(responseConverter(json))
|
||||||
logger.metric({ response_length: body.length })
|
logger.metric({ response_length: body.length })
|
||||||
logger.debug("RESPONSE: " + body)
|
logger.debug("RESPONSE: " + body)
|
||||||
|
await rateLimiter?.track()
|
||||||
await trackUsage(authInfo, modelInfo, providerInfo, json.usage)
|
await trackUsage(authInfo, modelInfo, providerInfo, json.usage)
|
||||||
await reload(authInfo)
|
await reload(authInfo)
|
||||||
return new Response(body, {
|
return new Response(body, {
|
||||||
@@ -131,6 +155,7 @@ export async function handler(
|
|||||||
response_length: responseLength,
|
response_length: responseLength,
|
||||||
"timestamp.last_byte": Date.now(),
|
"timestamp.last_byte": Date.now(),
|
||||||
})
|
})
|
||||||
|
await rateLimiter?.track()
|
||||||
const usage = usageParser.retrieve()
|
const usage = usageParser.retrieve()
|
||||||
if (usage) {
|
if (usage) {
|
||||||
await trackUsage(authInfo, modelInfo, providerInfo, usage)
|
await trackUsage(authInfo, modelInfo, providerInfo, usage)
|
||||||
@@ -150,7 +175,7 @@ export async function handler(
|
|||||||
responseLength += value.length
|
responseLength += value.length
|
||||||
buffer += decoder.decode(value, { stream: true })
|
buffer += decoder.decode(value, { stream: true })
|
||||||
|
|
||||||
const parts = buffer.split("\n\n")
|
const parts = buffer.split(providerInfo.streamSeparator)
|
||||||
buffer = parts.pop() ?? ""
|
buffer = parts.pop() ?? ""
|
||||||
|
|
||||||
for (let part of parts) {
|
for (let part of parts) {
|
||||||
@@ -205,6 +230,15 @@ export async function handler(
|
|||||||
{ status: 401 },
|
{ status: 401 },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (error instanceof RateLimitError)
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "error",
|
||||||
|
error: { type: error.constructor.name, message: error.message },
|
||||||
|
}),
|
||||||
|
{ status: 429 },
|
||||||
|
)
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -229,44 +263,43 @@ export async function handler(
|
|||||||
return { id: modelId, ...modelData }
|
return { id: modelId, ...modelData }
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectProvider(
|
function selectProvider(zenData: ZenData, modelInfo: ModelInfo, ip: string, retry: RetryOptions) {
|
||||||
zenData: ZenData,
|
const provider = (() => {
|
||||||
model: Awaited<ReturnType<typeof validateModel>>,
|
if (retry.retryCount === MAX_RETRIES) {
|
||||||
ip: string,
|
return modelInfo.providers.find((provider) => provider.id === modelInfo.fallbackProvider)
|
||||||
) {
|
}
|
||||||
const providers = model.providers
|
|
||||||
|
const providers = modelInfo.providers
|
||||||
.filter((provider) => !provider.disabled)
|
.filter((provider) => !provider.disabled)
|
||||||
|
.filter((provider) => !retry.excludeProviders.includes(provider.id))
|
||||||
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
|
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
|
||||||
|
|
||||||
// Use the last 2 characters of IP address to select a provider
|
// Use the last 2 characters of IP address to select a provider
|
||||||
const lastChars = ip.slice(-2)
|
const lastChars = ip.slice(-2)
|
||||||
const index = parseInt(lastChars, 16) % providers.length
|
const index = parseInt(lastChars, 16) % providers.length
|
||||||
const provider = providers[index || 0]
|
return providers[index || 0]
|
||||||
|
})()
|
||||||
|
|
||||||
if (!(provider.id in zenData.providers)) {
|
if (!provider) throw new ModelError("No provider available")
|
||||||
throw new ModelError(`Provider ${provider.id} not supported`)
|
if (!(provider.id in zenData.providers)) throw new ModelError(`Provider ${provider.id} not supported`)
|
||||||
}
|
|
||||||
|
|
||||||
const format = zenData.providers[provider.id].format
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...provider,
|
...provider,
|
||||||
...zenData.providers[provider.id],
|
...zenData.providers[provider.id],
|
||||||
...(format === "anthropic"
|
...(() => {
|
||||||
? anthropicHelper
|
const format = zenData.providers[provider.id].format
|
||||||
: format === "openai"
|
if (format === "anthropic") return anthropicHelper
|
||||||
? openaiHelper
|
if (format === "google") return googleHelper
|
||||||
: oaCompatHelper),
|
if (format === "openai") return openaiHelper
|
||||||
|
return oaCompatHelper
|
||||||
|
})(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function authenticate(
|
async function authenticate(modelInfo: ModelInfo, providerInfo: ProviderInfo) {
|
||||||
model: Awaited<ReturnType<typeof validateModel>>,
|
|
||||||
providerInfo: Awaited<ReturnType<typeof selectProvider>>,
|
|
||||||
) {
|
|
||||||
const apiKey = opts.parseApiKey(input.request.headers)
|
const apiKey = opts.parseApiKey(input.request.headers)
|
||||||
if (!apiKey) {
|
if (!apiKey || apiKey === "public") {
|
||||||
if (model.allowAnonymous) return
|
if (modelInfo.allowAnonymous) return
|
||||||
throw new AuthError("Missing API key.")
|
throw new AuthError("Missing API key.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,20 +330,11 @@ export async function handler(
|
|||||||
.from(KeyTable)
|
.from(KeyTable)
|
||||||
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
||||||
.innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID))
|
.innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID))
|
||||||
.innerJoin(
|
.innerJoin(UserTable, and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID)))
|
||||||
UserTable,
|
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, modelInfo.id)))
|
||||||
and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID)),
|
|
||||||
)
|
|
||||||
.leftJoin(
|
|
||||||
ModelTable,
|
|
||||||
and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, model.id)),
|
|
||||||
)
|
|
||||||
.leftJoin(
|
.leftJoin(
|
||||||
ProviderTable,
|
ProviderTable,
|
||||||
and(
|
and(eq(ProviderTable.workspaceID, KeyTable.workspaceID), eq(ProviderTable.provider, providerInfo.id)),
|
||||||
eq(ProviderTable.workspaceID, KeyTable.workspaceID),
|
|
||||||
eq(ProviderTable.provider, providerInfo.id),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
||||||
.then((rows) => rows[0]),
|
.then((rows) => rows[0]),
|
||||||
@@ -333,11 +357,11 @@ export async function handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateBilling(model: Model, authInfo: Awaited<ReturnType<typeof authenticate>>) {
|
function validateBilling(authInfo: AuthInfo, modelInfo: ModelInfo) {
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
if (authInfo.provider?.credentials) return
|
if (authInfo.provider?.credentials) return
|
||||||
if (authInfo.isFree) return
|
if (authInfo.isFree) return
|
||||||
if (model.allowAnonymous) return
|
if (modelInfo.allowAnonymous) return
|
||||||
|
|
||||||
const billing = authInfo.billing
|
const billing = authInfo.billing
|
||||||
if (!billing.paymentMethodID)
|
if (!billing.paymentMethodID)
|
||||||
@@ -381,39 +405,24 @@ export async function handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateModelSettings(authInfo: Awaited<ReturnType<typeof authenticate>>) {
|
function validateModelSettings(authInfo: AuthInfo) {
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
if (authInfo.isDisabled) throw new ModelError("Model is disabled")
|
if (authInfo.isDisabled) throw new ModelError("Model is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProviderKey(
|
function updateProviderKey(authInfo: AuthInfo, providerInfo: ProviderInfo) {
|
||||||
authInfo: Awaited<ReturnType<typeof authenticate>>,
|
|
||||||
providerInfo: Awaited<ReturnType<typeof selectProvider>>,
|
|
||||||
) {
|
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
if (!authInfo.provider?.credentials) return
|
if (!authInfo.provider?.credentials) return
|
||||||
providerInfo.apiKey = authInfo.provider.credentials
|
providerInfo.apiKey = authInfo.provider.credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
async function trackUsage(
|
async function trackUsage(authInfo: AuthInfo, modelInfo: ModelInfo, providerInfo: ProviderInfo, usage: any) {
|
||||||
authInfo: Awaited<ReturnType<typeof authenticate>>,
|
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } =
|
||||||
modelInfo: ReturnType<typeof validateModel>,
|
providerInfo.normalizeUsage(usage)
|
||||||
providerInfo: Awaited<ReturnType<typeof selectProvider>>,
|
|
||||||
usage: any,
|
|
||||||
) {
|
|
||||||
const {
|
|
||||||
inputTokens,
|
|
||||||
outputTokens,
|
|
||||||
reasoningTokens,
|
|
||||||
cacheReadTokens,
|
|
||||||
cacheWrite5mTokens,
|
|
||||||
cacheWrite1hTokens,
|
|
||||||
} = providerInfo.normalizeUsage(usage)
|
|
||||||
|
|
||||||
const modelCost =
|
const modelCost =
|
||||||
modelInfo.cost200K &&
|
modelInfo.cost200K &&
|
||||||
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) >
|
inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000
|
||||||
200_000
|
|
||||||
? modelInfo.cost200K
|
? modelInfo.cost200K
|
||||||
: modelInfo.cost
|
: modelInfo.cost
|
||||||
|
|
||||||
@@ -464,8 +473,7 @@ export async function handler(
|
|||||||
|
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
|
|
||||||
const cost =
|
const cost = authInfo.isFree || authInfo.provider?.credentials ? 0 : centsToMicroCents(totalCostInCent)
|
||||||
authInfo.isFree || authInfo.provider?.credentials ? 0 : centsToMicroCents(totalCostInCent)
|
|
||||||
await Database.transaction(async (tx) => {
|
await Database.transaction(async (tx) => {
|
||||||
await tx.insert(UsageTable).values({
|
await tx.insert(UsageTable).values({
|
||||||
workspaceID: authInfo.workspaceID,
|
workspaceID: authInfo.workspaceID,
|
||||||
@@ -505,9 +513,7 @@ export async function handler(
|
|||||||
`,
|
`,
|
||||||
timeMonthlyUsageUpdated: sql`now()`,
|
timeMonthlyUsageUpdated: sql`now()`,
|
||||||
})
|
})
|
||||||
.where(
|
.where(and(eq(UserTable.workspaceID, authInfo.workspaceID), eq(UserTable.id, authInfo.user.id)))
|
||||||
and(eq(UserTable.workspaceID, authInfo.workspaceID), eq(UserTable.id, authInfo.user.id)),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await Database.use((tx) =>
|
await Database.use((tx) =>
|
||||||
@@ -518,7 +524,7 @@ export async function handler(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reload(authInfo: Awaited<ReturnType<typeof authenticate>>) {
|
async function reload(authInfo: AuthInfo) {
|
||||||
if (!authInfo) return
|
if (!authInfo) return
|
||||||
if (authInfo.isFree) return
|
if (authInfo.isFree) return
|
||||||
if (authInfo.provider?.credentials) return
|
if (authInfo.provider?.credentials) return
|
||||||
@@ -537,10 +543,7 @@ export async function handler(
|
|||||||
BillingTable.balance,
|
BillingTable.balance,
|
||||||
centsToMicroCents((authInfo.billing.reloadTrigger ?? Billing.RELOAD_TRIGGER) * 100),
|
centsToMicroCents((authInfo.billing.reloadTrigger ?? Billing.RELOAD_TRIGGER) * 100),
|
||||||
),
|
),
|
||||||
or(
|
or(isNull(BillingTable.timeReloadLockedTill), lt(BillingTable.timeReloadLockedTill, sql`now()`)),
|
||||||
isNull(BillingTable.timeReloadLockedTill),
|
|
||||||
lt(BillingTable.timeReloadLockedTill, sql`now()`),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const anthropicHelper = {
|
|||||||
service_tier: "standard_only",
|
service_tier: "standard_only",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
streamSeparator: "\n\n",
|
||||||
createUsageParser: () => {
|
createUsageParser: () => {
|
||||||
let usage: Usage
|
let usage: Usage
|
||||||
|
|
||||||
@@ -123,15 +124,12 @@ export function fromAnthropicRequest(body: any): CommonRequest {
|
|||||||
if ((p as any).type === "tool_result") {
|
if ((p as any).type === "tool_result") {
|
||||||
const id = (p as any).tool_use_id
|
const id = (p as any).tool_use_id
|
||||||
const content =
|
const content =
|
||||||
typeof (p as any).content === "string"
|
typeof (p as any).content === "string" ? (p as any).content : JSON.stringify((p as any).content)
|
||||||
? (p as any).content
|
|
||||||
: JSON.stringify((p as any).content)
|
|
||||||
msgs.push({ role: "tool", tool_call_id: id, content })
|
msgs.push({ role: "tool", tool_call_id: id, content })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (partsOut.length > 0) {
|
if (partsOut.length > 0) {
|
||||||
if (partsOut.length === 1 && partsOut[0].type === "text")
|
if (partsOut.length === 1 && partsOut[0].type === "text") msgs.push({ role: "user", content: partsOut[0].text })
|
||||||
msgs.push({ role: "user", content: partsOut[0].text })
|
|
||||||
else msgs.push({ role: "user", content: partsOut })
|
else msgs.push({ role: "user", content: partsOut })
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -143,8 +141,7 @@ export function fromAnthropicRequest(body: any): CommonRequest {
|
|||||||
const tcs: any[] = []
|
const tcs: any[] = []
|
||||||
for (const p of partsIn) {
|
for (const p of partsIn) {
|
||||||
if (!p || !(p as any).type) continue
|
if (!p || !(p as any).type) continue
|
||||||
if ((p as any).type === "text" && typeof (p as any).text === "string")
|
if ((p as any).type === "text" && typeof (p as any).text === "string") texts.push((p as any).text)
|
||||||
texts.push((p as any).text)
|
|
||||||
if ((p as any).type === "tool_use") {
|
if ((p as any).type === "tool_use") {
|
||||||
const name = (p as any).name
|
const name = (p as any).name
|
||||||
const id = (p as any).id
|
const id = (p as any).id
|
||||||
@@ -214,9 +211,7 @@ export function fromAnthropicRequest(body: any): CommonRequest {
|
|||||||
export function toAnthropicRequest(body: CommonRequest) {
|
export function toAnthropicRequest(body: CommonRequest) {
|
||||||
if (!body || typeof body !== "object") return body
|
if (!body || typeof body !== "object") return body
|
||||||
|
|
||||||
const sysIn = Array.isArray(body.messages)
|
const sysIn = Array.isArray(body.messages) ? body.messages.filter((m: any) => m && m.role === "system") : []
|
||||||
? body.messages.filter((m: any) => m && m.role === "system")
|
|
||||||
: []
|
|
||||||
let ccCount = 0
|
let ccCount = 0
|
||||||
const cc = () => {
|
const cc = () => {
|
||||||
ccCount++
|
ccCount++
|
||||||
@@ -367,9 +362,7 @@ export function fromAnthropicResponse(resp: any): CommonResponse {
|
|||||||
|
|
||||||
const idIn = (resp as any).id
|
const idIn = (resp as any).id
|
||||||
const id =
|
const id =
|
||||||
typeof idIn === "string"
|
typeof idIn === "string" ? idIn.replace(/^msg_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}`
|
||||||
? idIn.replace(/^msg_/, "chatcmpl_")
|
|
||||||
: `chatcmpl_${Math.random().toString(36).slice(2)}`
|
|
||||||
const model = (resp as any).model
|
const model = (resp as any).model
|
||||||
|
|
||||||
const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : []
|
const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : []
|
||||||
@@ -412,9 +405,7 @@ export function fromAnthropicResponse(resp: any): CommonResponse {
|
|||||||
const ct = typeof (u as any).output_tokens === "number" ? (u as any).output_tokens : undefined
|
const ct = typeof (u as any).output_tokens === "number" ? (u as any).output_tokens : undefined
|
||||||
const total = pt != null && ct != null ? pt + ct : undefined
|
const total = pt != null && ct != null ? pt + ct : undefined
|
||||||
const cached =
|
const cached =
|
||||||
typeof (u as any).cache_read_input_tokens === "number"
|
typeof (u as any).cache_read_input_tokens === "number" ? (u as any).cache_read_input_tokens : undefined
|
||||||
? (u as any).cache_read_input_tokens
|
|
||||||
: undefined
|
|
||||||
const details = cached != null ? { cached_tokens: cached } : undefined
|
const details = cached != null ? { cached_tokens: cached } : undefined
|
||||||
return {
|
return {
|
||||||
prompt_tokens: pt,
|
prompt_tokens: pt,
|
||||||
@@ -591,9 +582,7 @@ export function fromAnthropicChunk(chunk: string): CommonChunk | string {
|
|||||||
prompt_tokens: u.input_tokens,
|
prompt_tokens: u.input_tokens,
|
||||||
completion_tokens: u.output_tokens,
|
completion_tokens: u.output_tokens,
|
||||||
total_tokens: (u.input_tokens || 0) + (u.output_tokens || 0),
|
total_tokens: (u.input_tokens || 0) + (u.output_tokens || 0),
|
||||||
...(u.cache_read_input_tokens
|
...(u.cache_read_input_tokens ? { prompt_tokens_details: { cached_tokens: u.cache_read_input_tokens } } : {}),
|
||||||
? { prompt_tokens_details: { cached_tokens: u.cache_read_input_tokens } }
|
|
||||||
: {}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { ProviderHelper } from "./provider"
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
promptTokenCount: 11453,
|
||||||
|
candidatesTokenCount: 71,
|
||||||
|
totalTokenCount: 11625,
|
||||||
|
cachedContentTokenCount: 8100,
|
||||||
|
promptTokensDetails: [
|
||||||
|
{modality: "TEXT",tokenCount: 11453}
|
||||||
|
],
|
||||||
|
cacheTokensDetails: [
|
||||||
|
{modality: "TEXT",tokenCount: 8100}
|
||||||
|
],
|
||||||
|
thoughtsTokenCount: 101
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
type Usage = {
|
||||||
|
promptTokenCount?: number
|
||||||
|
candidatesTokenCount?: number
|
||||||
|
totalTokenCount?: number
|
||||||
|
cachedContentTokenCount?: number
|
||||||
|
promptTokensDetails?: { modality: string; tokenCount: number }[]
|
||||||
|
cacheTokensDetails?: { modality: string; tokenCount: number }[]
|
||||||
|
thoughtsTokenCount?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const googleHelper = {
|
||||||
|
format: "google",
|
||||||
|
modifyUrl: (providerApi: string, model?: string, isStream?: boolean) =>
|
||||||
|
`${providerApi}/models/${model}:${isStream ? "streamGenerateContent?alt=sse" : "generateContent"}`,
|
||||||
|
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
|
||||||
|
headers.set("x-goog-api-key", apiKey)
|
||||||
|
},
|
||||||
|
modifyBody: (body: Record<string, any>) => {
|
||||||
|
return body
|
||||||
|
},
|
||||||
|
streamSeparator: "\r\n\r\n",
|
||||||
|
createUsageParser: () => {
|
||||||
|
let usage: Usage
|
||||||
|
|
||||||
|
return {
|
||||||
|
parse: (chunk: string) => {
|
||||||
|
if (!chunk.startsWith("data: ")) return
|
||||||
|
|
||||||
|
let json
|
||||||
|
try {
|
||||||
|
json = JSON.parse(chunk.slice(6)) as { usageMetadata?: Usage }
|
||||||
|
} catch (e) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json.usageMetadata) return
|
||||||
|
usage = json.usageMetadata
|
||||||
|
},
|
||||||
|
retrieve: () => usage,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
normalizeUsage: (usage: Usage) => {
|
||||||
|
const inputTokens = usage.promptTokenCount ?? 0
|
||||||
|
const outputTokens = usage.candidatesTokenCount ?? 0
|
||||||
|
const reasoningTokens = usage.thoughtsTokenCount ?? 0
|
||||||
|
const cacheReadTokens = usage.cachedContentTokenCount ?? 0
|
||||||
|
return {
|
||||||
|
inputTokens: inputTokens - cacheReadTokens,
|
||||||
|
outputTokens,
|
||||||
|
reasoningTokens,
|
||||||
|
cacheReadTokens,
|
||||||
|
cacheWrite5mTokens: undefined,
|
||||||
|
cacheWrite1hTokens: undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} satisfies ProviderHelper
|
||||||
@@ -33,6 +33,7 @@ export const oaCompatHelper = {
|
|||||||
...(body.stream ? { stream_options: { include_usage: true } } : {}),
|
...(body.stream ? { stream_options: { include_usage: true } } : {}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
streamSeparator: "\n\n",
|
||||||
createUsageParser: () => {
|
createUsageParser: () => {
|
||||||
let usage: Usage
|
let usage: Usage
|
||||||
|
|
||||||
@@ -57,8 +58,7 @@ export const oaCompatHelper = {
|
|||||||
const inputTokens = usage.prompt_tokens ?? 0
|
const inputTokens = usage.prompt_tokens ?? 0
|
||||||
const outputTokens = usage.completion_tokens ?? 0
|
const outputTokens = usage.completion_tokens ?? 0
|
||||||
const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? undefined
|
const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? undefined
|
||||||
const cacheReadTokens =
|
const cacheReadTokens = usage.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? undefined
|
||||||
usage.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? undefined
|
|
||||||
return {
|
return {
|
||||||
inputTokens: inputTokens - (cacheReadTokens ?? 0),
|
inputTokens: inputTokens - (cacheReadTokens ?? 0),
|
||||||
outputTokens,
|
outputTokens,
|
||||||
@@ -80,8 +80,7 @@ export function fromOaCompatibleRequest(body: any): CommonRequest {
|
|||||||
if (!m || !m.role) continue
|
if (!m || !m.role) continue
|
||||||
|
|
||||||
if (m.role === "system") {
|
if (m.role === "system") {
|
||||||
if (typeof m.content === "string" && m.content.length > 0)
|
if (typeof m.content === "string" && m.content.length > 0) msgsOut.push({ role: "system", content: m.content })
|
||||||
msgsOut.push({ role: "system", content: m.content })
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +91,10 @@ export function fromOaCompatibleRequest(body: any): CommonRequest {
|
|||||||
const parts: any[] = []
|
const parts: any[] = []
|
||||||
for (const p of m.content) {
|
for (const p of m.content) {
|
||||||
if (!p || !p.type) continue
|
if (!p || !p.type) continue
|
||||||
if (p.type === "text" && typeof p.text === "string")
|
if (p.type === "text" && typeof p.text === "string") parts.push({ type: "text", text: p.text })
|
||||||
parts.push({ type: "text", text: p.text })
|
|
||||||
if (p.type === "image_url") parts.push({ type: "image_url", image_url: p.image_url })
|
if (p.type === "image_url") parts.push({ type: "image_url", image_url: p.image_url })
|
||||||
}
|
}
|
||||||
if (parts.length === 1 && parts[0].type === "text")
|
if (parts.length === 1 && parts[0].type === "text") msgsOut.push({ role: "user", content: parts[0].text })
|
||||||
msgsOut.push({ role: "user", content: parts[0].text })
|
|
||||||
else if (parts.length > 0) msgsOut.push({ role: "user", content: parts })
|
else if (parts.length > 0) msgsOut.push({ role: "user", content: parts })
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -141,8 +138,7 @@ export function toOaCompatibleRequest(body: CommonRequest) {
|
|||||||
if (p.type === "image_url" && p.image_url) return { type: "image_url", image_url: p.image_url }
|
if (p.type === "image_url" && p.image_url) return { type: "image_url", image_url: p.image_url }
|
||||||
const s = (p as any).source
|
const s = (p as any).source
|
||||||
if (!s || typeof s !== "object") return undefined
|
if (!s || typeof s !== "object") return undefined
|
||||||
if (s.type === "url" && typeof s.url === "string")
|
if (s.type === "url" && typeof s.url === "string") return { type: "image_url", image_url: { url: s.url } }
|
||||||
return { type: "image_url", image_url: { url: s.url } }
|
|
||||||
if (s.type === "base64" && typeof s.media_type === "string" && typeof s.data === "string")
|
if (s.type === "base64" && typeof s.media_type === "string" && typeof s.data === "string")
|
||||||
return { type: "image_url", image_url: { url: `data:${s.media_type};base64,${s.data}` } }
|
return { type: "image_url", image_url: { url: `data:${s.media_type};base64,${s.data}` } }
|
||||||
return undefined
|
return undefined
|
||||||
@@ -152,8 +148,7 @@ export function toOaCompatibleRequest(body: CommonRequest) {
|
|||||||
if (!m || !m.role) continue
|
if (!m || !m.role) continue
|
||||||
|
|
||||||
if (m.role === "system") {
|
if (m.role === "system") {
|
||||||
if (typeof m.content === "string" && m.content.length > 0)
|
if (typeof m.content === "string" && m.content.length > 0) msgsOut.push({ role: "system", content: m.content })
|
||||||
msgsOut.push({ role: "system", content: m.content })
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,13 +161,11 @@ export function toOaCompatibleRequest(body: CommonRequest) {
|
|||||||
const parts: any[] = []
|
const parts: any[] = []
|
||||||
for (const p of m.content) {
|
for (const p of m.content) {
|
||||||
if (!p || !p.type) continue
|
if (!p || !p.type) continue
|
||||||
if (p.type === "text" && typeof p.text === "string")
|
if (p.type === "text" && typeof p.text === "string") parts.push({ type: "text", text: p.text })
|
||||||
parts.push({ type: "text", text: p.text })
|
|
||||||
const ip = toImg(p)
|
const ip = toImg(p)
|
||||||
if (ip) parts.push(ip)
|
if (ip) parts.push(ip)
|
||||||
}
|
}
|
||||||
if (parts.length === 1 && parts[0].type === "text")
|
if (parts.length === 1 && parts[0].type === "text") msgsOut.push({ role: "user", content: parts[0].text })
|
||||||
msgsOut.push({ role: "user", content: parts[0].text })
|
|
||||||
else if (parts.length > 0) msgsOut.push({ role: "user", content: parts })
|
else if (parts.length > 0) msgsOut.push({ role: "user", content: parts })
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -325,9 +318,7 @@ export function toOaCompatibleResponse(resp: CommonResponse) {
|
|||||||
|
|
||||||
const idIn = (resp as any).id
|
const idIn = (resp as any).id
|
||||||
const id =
|
const id =
|
||||||
typeof idIn === "string"
|
typeof idIn === "string" ? idIn.replace(/^msg_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}`
|
||||||
? idIn.replace(/^msg_/, "chatcmpl_")
|
|
||||||
: `chatcmpl_${Math.random().toString(36).slice(2)}`
|
|
||||||
const model = (resp as any).model
|
const model = (resp as any).model
|
||||||
|
|
||||||
const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : []
|
const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : []
|
||||||
@@ -369,8 +360,7 @@ export function toOaCompatibleResponse(resp: CommonResponse) {
|
|||||||
const pt = typeof u.input_tokens === "number" ? u.input_tokens : undefined
|
const pt = typeof u.input_tokens === "number" ? u.input_tokens : undefined
|
||||||
const ct = typeof u.output_tokens === "number" ? u.output_tokens : undefined
|
const ct = typeof u.output_tokens === "number" ? u.output_tokens : undefined
|
||||||
const total = pt != null && ct != null ? pt + ct : undefined
|
const total = pt != null && ct != null ? pt + ct : undefined
|
||||||
const cached =
|
const cached = typeof u.cache_read_input_tokens === "number" ? u.cache_read_input_tokens : undefined
|
||||||
typeof u.cache_read_input_tokens === "number" ? u.cache_read_input_tokens : undefined
|
|
||||||
const details = cached != null ? { cached_tokens: cached } : undefined
|
const details = cached != null ? { cached_tokens: cached } : undefined
|
||||||
return {
|
return {
|
||||||
prompt_tokens: pt,
|
prompt_tokens: pt,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export const openaiHelper = {
|
|||||||
modifyBody: (body: Record<string, any>) => {
|
modifyBody: (body: Record<string, any>) => {
|
||||||
return body
|
return body
|
||||||
},
|
},
|
||||||
|
streamSeparator: "\n\n",
|
||||||
createUsageParser: () => {
|
createUsageParser: () => {
|
||||||
let usage: Usage
|
let usage: Usage
|
||||||
|
|
||||||
@@ -86,11 +87,7 @@ export function fromOpenaiRequest(body: any): CommonRequest {
|
|||||||
|
|
||||||
const msgs: any[] = []
|
const msgs: any[] = []
|
||||||
|
|
||||||
const inMsgs = Array.isArray(body.input)
|
const inMsgs = Array.isArray(body.input) ? body.input : Array.isArray(body.messages) ? body.messages : []
|
||||||
? body.input
|
|
||||||
: Array.isArray(body.messages)
|
|
||||||
? body.messages
|
|
||||||
: []
|
|
||||||
|
|
||||||
for (const m of inMsgs) {
|
for (const m of inMsgs) {
|
||||||
if (!m) continue
|
if (!m) continue
|
||||||
@@ -103,9 +100,7 @@ export function fromOpenaiRequest(body: any): CommonRequest {
|
|||||||
const args = typeof a === "string" ? a : JSON.stringify(a ?? {})
|
const args = typeof a === "string" ? a : JSON.stringify(a ?? {})
|
||||||
msgs.push({
|
msgs.push({
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
tool_calls: [
|
tool_calls: [{ id: (m as any).id, type: "function", function: { name, arguments: args } }],
|
||||||
{ id: (m as any).id, type: "function", function: { name, arguments: args } },
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if ((m as any).type === "function_call_output") {
|
if ((m as any).type === "function_call_output") {
|
||||||
@@ -122,8 +117,7 @@ export function fromOpenaiRequest(body: any): CommonRequest {
|
|||||||
if (typeof c === "string" && c.length > 0) msgs.push({ role: "system", content: c })
|
if (typeof c === "string" && c.length > 0) msgs.push({ role: "system", content: c })
|
||||||
if (Array.isArray(c)) {
|
if (Array.isArray(c)) {
|
||||||
const t = c.find((p: any) => p && typeof p.text === "string")
|
const t = c.find((p: any) => p && typeof p.text === "string")
|
||||||
if (t && typeof t.text === "string" && t.text.length > 0)
|
if (t && typeof t.text === "string" && t.text.length > 0) msgs.push({ role: "system", content: t.text })
|
||||||
msgs.push({ role: "system", content: t.text })
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -136,24 +130,18 @@ export function fromOpenaiRequest(body: any): CommonRequest {
|
|||||||
const parts: any[] = []
|
const parts: any[] = []
|
||||||
for (const p of c) {
|
for (const p of c) {
|
||||||
if (!p || !(p as any).type) continue
|
if (!p || !(p as any).type) continue
|
||||||
if (
|
if (((p as any).type === "text" || (p as any).type === "input_text") && typeof (p as any).text === "string")
|
||||||
((p as any).type === "text" || (p as any).type === "input_text") &&
|
|
||||||
typeof (p as any).text === "string"
|
|
||||||
)
|
|
||||||
parts.push({ type: "text", text: (p as any).text })
|
parts.push({ type: "text", text: (p as any).text })
|
||||||
const ip = toImg(p)
|
const ip = toImg(p)
|
||||||
if (ip) parts.push(ip)
|
if (ip) parts.push(ip)
|
||||||
if ((p as any).type === "tool_result") {
|
if ((p as any).type === "tool_result") {
|
||||||
const id = (p as any).tool_call_id
|
const id = (p as any).tool_call_id
|
||||||
const content =
|
const content =
|
||||||
typeof (p as any).content === "string"
|
typeof (p as any).content === "string" ? (p as any).content : JSON.stringify((p as any).content)
|
||||||
? (p as any).content
|
|
||||||
: JSON.stringify((p as any).content)
|
|
||||||
msgs.push({ role: "tool", tool_call_id: id, content })
|
msgs.push({ role: "tool", tool_call_id: id, content })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parts.length === 1 && parts[0].type === "text")
|
if (parts.length === 1 && parts[0].type === "text") msgs.push({ role: "user", content: parts[0].text })
|
||||||
msgs.push({ role: "user", content: parts[0].text })
|
|
||||||
else if (parts.length > 0) msgs.push({ role: "user", content: parts })
|
else if (parts.length > 0) msgs.push({ role: "user", content: parts })
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@@ -280,10 +268,7 @@ export function toOpenaiRequest(body: CommonRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((m as any).role === "tool") {
|
if ((m as any).role === "tool") {
|
||||||
const out =
|
const out = typeof (m as any).content === "string" ? (m as any).content : JSON.stringify((m as any).content)
|
||||||
typeof (m as any).content === "string"
|
|
||||||
? (m as any).content
|
|
||||||
: JSON.stringify((m as any).content)
|
|
||||||
input.push({ type: "function_call_output", call_id: (m as any).tool_call_id, output: out })
|
input.push({ type: "function_call_output", call_id: (m as any).tool_call_id, output: out })
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -351,9 +336,7 @@ export function fromOpenaiResponse(resp: any): CommonResponse {
|
|||||||
|
|
||||||
const idIn = (r as any).id
|
const idIn = (r as any).id
|
||||||
const id =
|
const id =
|
||||||
typeof idIn === "string"
|
typeof idIn === "string" ? idIn.replace(/^resp_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}`
|
||||||
? idIn.replace(/^resp_/, "chatcmpl_")
|
|
||||||
: `chatcmpl_${Math.random().toString(36).slice(2)}`
|
|
||||||
const model = (r as any).model ?? (resp as any).model
|
const model = (r as any).model ?? (resp as any).model
|
||||||
|
|
||||||
const out = Array.isArray((r as any).output) ? (r as any).output : []
|
const out = Array.isArray((r as any).output) ? (r as any).output : []
|
||||||
@@ -480,9 +463,7 @@ export function toOpenaiResponse(resp: CommonResponse) {
|
|||||||
})()
|
})()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id:
|
id: (resp as any).id?.replace(/^chatcmpl_/, "resp_") ?? `resp_${Math.random().toString(36).slice(2)}`,
|
||||||
(resp as any).id?.replace(/^chatcmpl_/, "resp_") ??
|
|
||||||
`resp_${Math.random().toString(36).slice(2)}`,
|
|
||||||
object: "response",
|
object: "response",
|
||||||
model: (resp as any).model,
|
model: (resp as any).model,
|
||||||
output: outputItems,
|
output: outputItems,
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ import {
|
|||||||
|
|
||||||
export type ProviderHelper = {
|
export type ProviderHelper = {
|
||||||
format: ZenData.Format
|
format: ZenData.Format
|
||||||
modifyUrl: (providerApi: string) => string
|
modifyUrl: (providerApi: string, model?: string, isStream?: boolean) => string
|
||||||
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => void
|
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => void
|
||||||
modifyBody: (body: Record<string, any>) => Record<string, any>
|
modifyBody: (body: Record<string, any>) => Record<string, any>
|
||||||
|
streamSeparator: string
|
||||||
createUsageParser: () => {
|
createUsageParser: () => {
|
||||||
parse: (chunk: string) => void
|
parse: (chunk: string) => void
|
||||||
retrieve: () => any
|
retrieve: () => any
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { Resource } from "@opencode-ai/console-resource"
|
||||||
|
import { RateLimitError } from "./error"
|
||||||
|
import { logger } from "./logger"
|
||||||
|
|
||||||
|
export function createRateLimiter(model: string, limit: number | undefined, ip: string) {
|
||||||
|
if (!limit) return
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
const currKey = `usage:${ip}:${model}:${buildYYYYMMDDHH(now)}`
|
||||||
|
const prevKey = `usage:${ip}:${model}:${buildYYYYMMDDHH(now - 3_600_000)}`
|
||||||
|
let currRate: number
|
||||||
|
let prevRate: number
|
||||||
|
|
||||||
|
return {
|
||||||
|
track: async () => {
|
||||||
|
await Resource.GatewayKv.put(currKey, currRate + 1, { expirationTtl: 3600 })
|
||||||
|
},
|
||||||
|
check: async () => {
|
||||||
|
const values = await Resource.GatewayKv.get([currKey, prevKey])
|
||||||
|
const prevValue = values?.get(prevKey)
|
||||||
|
const currValue = values?.get(currKey)
|
||||||
|
prevRate = prevValue ? parseInt(prevValue) : 0
|
||||||
|
currRate = currValue ? parseInt(currValue) : 0
|
||||||
|
logger.debug(`rate limit ${model} prev/curr: ${prevRate}/${currRate}`)
|
||||||
|
if (prevRate + currRate >= limit) throw new RateLimitError(`Rate limit exceeded. Please try again later.`)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildYYYYMMDDHH(timestamp: number) {
|
||||||
|
return new Date(timestamp)
|
||||||
|
.toISOString()
|
||||||
|
.replace(/[^0-9]/g, "")
|
||||||
|
.substring(0, 10)
|
||||||
|
}
|
||||||
@@ -5,5 +5,7 @@ export function POST(input: APIEvent) {
|
|||||||
return handler(input, {
|
return handler(input, {
|
||||||
format: "oa-compat",
|
format: "oa-compat",
|
||||||
parseApiKey: (headers: Headers) => headers.get("authorization")?.split(" ")[1],
|
parseApiKey: (headers: Headers) => headers.get("authorization")?.split(" ")[1],
|
||||||
|
parseModel: (url: string, body: any) => body.model,
|
||||||
|
parseIsStream: (url: string, body: any) => !!body.stream,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ export function POST(input: APIEvent) {
|
|||||||
return handler(input, {
|
return handler(input, {
|
||||||
format: "anthropic",
|
format: "anthropic",
|
||||||
parseApiKey: (headers: Headers) => headers.get("x-api-key") ?? undefined,
|
parseApiKey: (headers: Headers) => headers.get("x-api-key") ?? undefined,
|
||||||
|
parseModel: (url: string, body: any) => body.model,
|
||||||
|
parseIsStream: (url: string, body: any) => !!body.stream,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,10 +50,7 @@ export async function GET(input: APIEvent) {
|
|||||||
})
|
})
|
||||||
.from(KeyTable)
|
.from(KeyTable)
|
||||||
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
||||||
.leftJoin(
|
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)))
|
||||||
ModelTable,
|
|
||||||
and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)),
|
|
||||||
)
|
|
||||||
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
||||||
.then((rows) => rows.map((row) => row.model)),
|
.then((rows) => rows.map((row) => row.model)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import type { APIEvent } from "@solidjs/start/server"
|
||||||
|
import { handler } from "~/routes/zen/util/handler"
|
||||||
|
|
||||||
|
export function POST(input: APIEvent) {
|
||||||
|
return handler(input, {
|
||||||
|
format: "google",
|
||||||
|
parseApiKey: (headers: Headers) => headers.get("x-goog-api-key") ?? undefined,
|
||||||
|
parseModel: (url: string, body: any) => url.split("/").pop()?.split(":")?.[0] ?? "",
|
||||||
|
parseIsStream: (url: string, body: any) =>
|
||||||
|
// ie. url: https://opencode.ai/zen/v1/models/gemini-3-pro:streamGenerateContent?alt=sse'
|
||||||
|
url.split("/").pop()?.split(":")?.[1]?.startsWith("streamGenerateContent") ?? false,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -5,5 +5,7 @@ export function POST(input: APIEvent) {
|
|||||||
return handler(input, {
|
return handler(input, {
|
||||||
format: "openai",
|
format: "openai",
|
||||||
parseApiKey: (headers: Headers) => headers.get("authorization")?.split(" ")[1],
|
parseApiKey: (headers: Headers) => headers.get("authorization")?.split(" ")[1],
|
||||||
|
parseModel: (url: string, body: any) => body.model,
|
||||||
|
parseIsStream: (url: string, body: any) => !!body.stream,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ body {
|
|||||||
--font-size-9xl: 8rem;
|
--font-size-9xl: 8rem;
|
||||||
|
|
||||||
--font-mono:
|
--font-mono:
|
||||||
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
"Courier New", monospace;
|
|
||||||
--font-sans: var(--font-mono);
|
--font-sans: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.0.36",
|
"version": "1.0.85",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -8,22 +8,15 @@ if (!email) {
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const authData = await printTable("Auth", (tx) =>
|
const authData = await printTable("Auth", (tx) => tx.select().from(AuthTable).where(eq(AuthTable.subject, email)))
|
||||||
tx.select().from(AuthTable).where(eq(AuthTable.subject, email)),
|
|
||||||
)
|
|
||||||
if (authData.length === 0) {
|
if (authData.length === 0) {
|
||||||
console.error("User not found")
|
console.error("User not found")
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
await printTable("Auth", (tx) =>
|
await printTable("Auth", (tx) => tx.select().from(AuthTable).where(eq(AuthTable.accountID, authData[0].accountID)))
|
||||||
tx.select().from(AuthTable).where(eq(AuthTable.accountID, authData[0].accountID)),
|
|
||||||
)
|
|
||||||
|
|
||||||
function printTable(
|
function printTable(title: string, callback: (tx: Database.TxOrDb) => Promise<any[]>): Promise<any[]> {
|
||||||
title: string,
|
|
||||||
callback: (tx: Database.TxOrDb) => Promise<any[]>,
|
|
||||||
): Promise<any[]> {
|
|
||||||
return Database.use(async (tx) => {
|
return Database.use(async (tx) => {
|
||||||
const data = await callback(tx)
|
const data = await callback(tx)
|
||||||
console.log(`== ${title} ==`)
|
console.log(`== ${title} ==`)
|
||||||
|
|||||||
@@ -8,14 +8,6 @@ import { KeyTable } from "../src/schema/key.sql.js"
|
|||||||
|
|
||||||
if (Resource.App.stage !== "frank") throw new Error("This script is only for frank")
|
if (Resource.App.stage !== "frank") throw new Error("This script is only for frank")
|
||||||
|
|
||||||
for (const table of [
|
for (const table of [AccountTable, BillingTable, KeyTable, PaymentTable, UsageTable, UserTable, WorkspaceTable]) {
|
||||||
AccountTable,
|
|
||||||
BillingTable,
|
|
||||||
KeyTable,
|
|
||||||
PaymentTable,
|
|
||||||
UsageTable,
|
|
||||||
UserTable,
|
|
||||||
WorkspaceTable,
|
|
||||||
]) {
|
|
||||||
await Database.use((tx) => tx.delete(table))
|
await Database.use((tx) => tx.delete(table))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { ZenData } from "../src/model"
|
|||||||
|
|
||||||
const root = path.resolve(process.cwd(), "..", "..", "..")
|
const root = path.resolve(process.cwd(), "..", "..", "..")
|
||||||
const models = await $`bun sst secret list`.cwd(root).text()
|
const models = await $`bun sst secret list`.cwd(root).text()
|
||||||
console.log("models", models)
|
|
||||||
|
|
||||||
// read the line starting with "ZEN_MODELS"
|
// read the line starting with "ZEN_MODELS"
|
||||||
const oldValue1 = models
|
const oldValue1 = models
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ export namespace AWS {
|
|||||||
body: z.string(),
|
body: z.string(),
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
const res = await createClient().fetch(
|
const res = await createClient().fetch("https://email.us-east-1.amazonaws.com/v2/email/outbound-emails", {
|
||||||
"https://email.us-east-1.amazonaws.com/v2/email/outbound-emails",
|
|
||||||
{
|
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"X-Amz-Target": "SES.SendEmail",
|
"X-Amz-Target": "SES.SendEmail",
|
||||||
@@ -56,8 +54,7 @@ export namespace AWS {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`Failed to send email: ${res.statusText}`)
|
throw new Error(`Failed to send email: ${res.statusText}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,14 +57,15 @@ export namespace Billing {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usages = async () => {
|
export const usages = async (page = 0, pageSize = 50) => {
|
||||||
return await Database.use((tx) =>
|
return await Database.use((tx) =>
|
||||||
tx
|
tx
|
||||||
.select()
|
.select()
|
||||||
.from(UsageTable)
|
.from(UsageTable)
|
||||||
.where(eq(UsageTable.workspaceID, Actor.workspace()))
|
.where(eq(UsageTable.workspaceID, Actor.workspace()))
|
||||||
.orderBy(sql`${UsageTable.timeCreated} DESC`)
|
.orderBy(sql`${UsageTable.timeCreated} DESC`)
|
||||||
.limit(100),
|
.limit(pageSize)
|
||||||
|
.offset(page * pageSize),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import { Client } from "@planetscale/database"
|
|||||||
|
|
||||||
import { MySqlTransaction, type MySqlTransactionConfig } from "drizzle-orm/mysql-core"
|
import { MySqlTransaction, type MySqlTransactionConfig } from "drizzle-orm/mysql-core"
|
||||||
import type { ExtractTablesWithRelations } from "drizzle-orm"
|
import type { ExtractTablesWithRelations } from "drizzle-orm"
|
||||||
import type {
|
import type { PlanetScalePreparedQueryHKT, PlanetscaleQueryResultHKT } from "drizzle-orm/planetscale-serverless"
|
||||||
PlanetScalePreparedQueryHKT,
|
|
||||||
PlanetscaleQueryResultHKT,
|
|
||||||
} from "drizzle-orm/planetscale-serverless"
|
|
||||||
import { Context } from "../context"
|
import { Context } from "../context"
|
||||||
import { memo } from "../util/memo"
|
import { memo } from "../util/memo"
|
||||||
|
|
||||||
@@ -70,10 +67,7 @@ export namespace Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function transaction<T>(
|
export async function transaction<T>(callback: (tx: TxOrDb) => Promise<T>, config?: MySqlTransactionConfig) {
|
||||||
callback: (tx: TxOrDb) => Promise<T>,
|
|
||||||
config?: MySqlTransactionConfig,
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
const { tx } = TransactionContext.use()
|
const { tx } = TransactionContext.use()
|
||||||
return callback(tx)
|
return callback(tx)
|
||||||
|
|||||||
@@ -20,14 +20,8 @@ export namespace Key {
|
|||||||
email: AuthTable.subject,
|
email: AuthTable.subject,
|
||||||
})
|
})
|
||||||
.from(KeyTable)
|
.from(KeyTable)
|
||||||
.innerJoin(
|
.innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID)))
|
||||||
UserTable,
|
.innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")))
|
||||||
and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID)),
|
|
||||||
)
|
|
||||||
.innerJoin(
|
|
||||||
AuthTable,
|
|
||||||
and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")),
|
|
||||||
)
|
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
...[
|
...[
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Actor } from "./actor"
|
|||||||
import { Resource } from "@opencode-ai/console-resource"
|
import { Resource } from "@opencode-ai/console-resource"
|
||||||
|
|
||||||
export namespace ZenData {
|
export namespace ZenData {
|
||||||
const FormatSchema = z.enum(["anthropic", "openai", "oa-compat"])
|
const FormatSchema = z.enum(["anthropic", "google", "openai", "oa-compat"])
|
||||||
export type Format = z.infer<typeof FormatSchema>
|
export type Format = z.infer<typeof FormatSchema>
|
||||||
|
|
||||||
const ModelCostSchema = z.object({
|
const ModelCostSchema = z.object({
|
||||||
@@ -24,6 +24,8 @@ export namespace ZenData {
|
|||||||
cost: ModelCostSchema,
|
cost: ModelCostSchema,
|
||||||
cost200K: ModelCostSchema.optional(),
|
cost200K: ModelCostSchema.optional(),
|
||||||
allowAnonymous: z.boolean().optional(),
|
allowAnonymous: z.boolean().optional(),
|
||||||
|
rateLimit: z.number().optional(),
|
||||||
|
fallbackProvider: z.string().optional(),
|
||||||
providers: z.array(
|
providers: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
@@ -60,9 +62,7 @@ export namespace Model {
|
|||||||
export const enable = fn(z.object({ model: z.string() }), ({ model }) => {
|
export const enable = fn(z.object({ model: z.string() }), ({ model }) => {
|
||||||
Actor.assertAdmin()
|
Actor.assertAdmin()
|
||||||
return Database.use((db) =>
|
return Database.use((db) =>
|
||||||
db
|
db.delete(ModelTable).where(and(eq(ModelTable.workspaceID, Actor.workspace()), eq(ModelTable.model, model))),
|
||||||
.delete(ModelTable)
|
|
||||||
.where(and(eq(ModelTable.workspaceID, Actor.workspace()), eq(ModelTable.model, model))),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ export namespace Provider {
|
|||||||
tx
|
tx
|
||||||
.select()
|
.select()
|
||||||
.from(ProviderTable)
|
.from(ProviderTable)
|
||||||
.where(
|
.where(and(eq(ProviderTable.workspaceID, Actor.workspace()), isNull(ProviderTable.timeDeleted))),
|
||||||
and(eq(ProviderTable.workspaceID, Actor.workspace()), isNull(ProviderTable.timeDeleted)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,12 +50,7 @@ export namespace Provider {
|
|||||||
return Database.transaction((tx) =>
|
return Database.transaction((tx) =>
|
||||||
tx
|
tx
|
||||||
.delete(ProviderTable)
|
.delete(ProviderTable)
|
||||||
.where(
|
.where(and(eq(ProviderTable.provider, provider), eq(ProviderTable.workspaceID, Actor.workspace()))),
|
||||||
and(
|
|
||||||
eq(ProviderTable.provider, provider),
|
|
||||||
eq(ProviderTable.workspaceID, Actor.workspace()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import {
|
import { index, mysqlEnum, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core"
|
||||||
index,
|
|
||||||
mysqlEnum,
|
|
||||||
mysqlTable,
|
|
||||||
primaryKey,
|
|
||||||
uniqueIndex,
|
|
||||||
varchar,
|
|
||||||
} from "drizzle-orm/mysql-core"
|
|
||||||
import { id, timestamps, ulid } from "../drizzle/types"
|
import { id, timestamps, ulid } from "../drizzle/types"
|
||||||
|
|
||||||
export const AuthProvider = ["email", "github", "google"] as const
|
export const AuthProvider = ["email", "github", "google"] as const
|
||||||
|
|||||||
@@ -9,8 +9,5 @@ export const ModelTable = mysqlTable(
|
|||||||
...timestamps,
|
...timestamps,
|
||||||
model: varchar("model", { length: 64 }).notNull(),
|
model: varchar("model", { length: 64 }).notNull(),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [...workspaceIndexes(table), uniqueIndex("model_workspace_model").on(table.workspaceID, table.model)],
|
||||||
...workspaceIndexes(table),
|
|
||||||
uniqueIndex("model_workspace_model").on(table.workspaceID, table.model),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,8 +10,5 @@ export const ProviderTable = mysqlTable(
|
|||||||
provider: varchar("provider", { length: 64 }).notNull(),
|
provider: varchar("provider", { length: 64 }).notNull(),
|
||||||
credentials: text("credentials").notNull(),
|
credentials: text("credentials").notNull(),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [...workspaceIndexes(table), uniqueIndex("workspace_provider").on(table.workspaceID, table.provider)],
|
||||||
...workspaceIndexes(table),
|
|
||||||
uniqueIndex("workspace_provider").on(table.workspaceID, table.provider),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user