chore: merge dev into v2 by opencode-agent[bot] · Pull Request #36312 · anomalyco/opencode · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
417 commits
Select commit Hold shift + click to select a range
45a437c
fix(app): clamp virtualizer range to scroll bounds (#34588)
opencode-agent[bot] Jul 1, 2026
2b611a5
chore: update nix node_modules hashes
opencode-agent[bot] Jul 1, 2026
55552c5
fix(provider): force openai reasoning variants (#34702)
rekram1-node Jul 1, 2026
af72cec
feat(desktop): scope tabs to windows (#34669)
Brendonovich Jul 1, 2026
bd7f7ad
chore: generate
opencode-agent[bot] Jul 1, 2026
5e1a1ed
fix(app): scope session page errors (#34254)
Brendonovich Jul 1, 2026
bf18cc9
chore: generate
opencode-agent[bot] Jul 1, 2026
4d91f0c
feat(app): v2 wsl ui (#34233)
arvsrn Jul 1, 2026
34ee942
chore: generate
opencode-agent[bot] Jul 1, 2026
cd00422
fix(app): question UI fixes and UX improvements (#34116)
eXamadeus Jul 1, 2026
6f2ff35
chore: generate
opencode-agent[bot] Jul 1, 2026
2f4d36d
fix(desktop): clean stale draft stores (#34651)
Brendonovich Jul 1, 2026
8b68dc0
chore: generate
opencode-agent[bot] Jul 1, 2026
f014686
feat(desktop): session tab hover preview popover (#34678)
usrnk1 Jul 1, 2026
9410eda
feat(app): composer improvements (#34720)
arvsrn Jul 1, 2026
4b1c7f2
chore: generate
opencode-agent[bot] Jul 1, 2026
246dea3
feat(app): more v2 ui alignment (#34465)
arvsrn Jul 1, 2026
3136b1b
feat(desktop): improve markdown heading spacing in session timeline (…
usrnk1 Jul 1, 2026
87aa62d
chore: generate
opencode-agent[bot] Jul 1, 2026
6697cf3
feat(app): minor fixes (#34748)
arvsrn Jul 1, 2026
1e73b76
sync release versions for v1.17.13
Jul 1, 2026
9495e3e
chore: bump gitlab-ai-provider to 6.10.0 (#34756)
vglafirov Jul 1, 2026
7de5aa0
chore: update nix node_modules hashes
opencode-agent[bot] Jul 1, 2026
74e5644
feat(stats): redesign lab hero
adamdotdevin Jul 1, 2026
262ef4f
feat(stats): add lab overview
adamdotdevin Jul 1, 2026
91ca75c
feat(stats): redesign lab usage
adamdotdevin Jul 1, 2026
85e8ac3
feat(data): another redesigned lab section
adamdotdevin Jul 1, 2026
3706b33
feat(stats): use catalog descriptions
adamdotdevin Jul 1, 2026
5668d36
chore: generate
opencode-agent[bot] Jul 1, 2026
beb586a
fix(stats): refine lab page tooltips
adamdotdevin Jul 1, 2026
fc29f99
fix(stats): include locale header in vary (#34789)
adamdotdevin Jul 1, 2026
3df5556
zen: new inference
fwang Jul 1, 2026
f266e82
fix(desktop): keep window tabs across app close (#34807)
Hona Jul 1, 2026
3cf7180
fix(app): stabilize session timeline layout continuity (#34533)
Hona Jul 2, 2026
917eca4
feat(desktop): refine session tab preview popover (#34792)
usrnk1 Jul 2, 2026
4de7e90
fix(ui): raise v2 tooltip layer (#34455)
opencode-agent[bot] Jul 2, 2026
b393499
chore: update nix node_modules hashes
opencode-agent[bot] Jul 2, 2026
6ca60d9
fix(opencode): update Cerebras SDK reasoning replay (#34826)
opencode-agent[bot] Jul 2, 2026
a39db9c
chore: update nix node_modules hashes
opencode-agent[bot] Jul 2, 2026
39dfbb5
fix(app): resolve target session lineage outside router transition (#…
Hona Jul 2, 2026
d6b8971
chore: generate
opencode-agent[bot] Jul 2, 2026
a0d64b1
fix(opencode): filter session list by resolved instance directory (#3…
Hona Jul 2, 2026
5fecf7a
fix(app): only allow \(...\) syntax for inline latex (#34850)
Brendonovich Jul 2, 2026
27c9b13
test(opencode): cover Windows session list directory spellings (#34857)
Hona Jul 2, 2026
1fb2ecc
fix(app): scope session tab indicators to the tab's server (#34861)
Hona Jul 2, 2026
403164a
chore: generate
opencode-agent[bot] Jul 2, 2026
4023359
fix(app): clear original prompt after retarget (#34863)
Brendonovich Jul 2, 2026
fbb95a6
fix(app): seed session status before warming session info (#34864)
Hona Jul 2, 2026
7d26186
feat(app): v2 review panel overhaul (#31882)
arvsrn Jul 2, 2026
4a42cae
fix(app): keep terminal mounted when switching session tabs in a work…
Hona Jul 2, 2026
f52424e
fix(ui): resolve toast icon inside the toast component (#34874)
Hona Jul 2, 2026
373cd08
fix(copilot): honor advertised model endpoints (#34958)
rekram1-node Jul 2, 2026
7457139
fix(stats): polish lab pages
adamdotdevin Jul 2, 2026
299daa2
feat(stats): redesign model hero
adamdotdevin Jul 2, 2026
5ecd19d
chore: generate
opencode-agent[bot] Jul 2, 2026
3adfb97
feat(tui): add debug info dialog with copy to clipboard (#35004)
StarpTech Jul 2, 2026
cb54824
zen: new inference
fwang Jul 3, 2026
20b090e
zen: new inference
fwang Jul 3, 2026
c07ac0d
feat(app): navigate tabs on mousedown in new layout (#35042)
Hona Jul 3, 2026
6dba0cc
zen: new inference
fwang Jul 3, 2026
5455fed
zen: new inference
fwang Jul 3, 2026
04d236c
fix(app): keep v2 review pane mounted across session tab switches (#3…
Hona Jul 3, 2026
cb93114
feat: experimental codemode (#34677)
rekram1-node Jul 3, 2026
83c638e
chore: generate
opencode-agent[bot] Jul 3, 2026
2ef1a59
fix(ci): setup Node 24 before bun install for node-gyp (#35076)
Hona Jul 3, 2026
379adee
revert: back out experimental codemode (#35077)
rekram1-node Jul 3, 2026
2409c7a
feat(codemode): add confined execution package (#35079)
rekram1-node Jul 3, 2026
3f0fc22
chore: generate
opencode-agent[bot] Jul 3, 2026
7d48a22
chore: update nix node_modules hashes
opencode-agent[bot] Jul 3, 2026
eb34766
chore: remove root node-gyp pin after Node 24 setup (#35092)
rekram1-node Jul 3, 2026
bf58fae
feat(desktop): add recently closed projects to home (#34926)
usrnk1 Jul 3, 2026
4c6e2a9
feat(app): align subagent UI with v2 (#34931)
arvsrn Jul 3, 2026
caedf36
chore: generate
opencode-agent[bot] Jul 3, 2026
d46c02b
feat(desktop): papercut fixes (#34939)
usrnk1 Jul 3, 2026
458ec7b
refactor(opencode): expose MCP tools in native shape from the service…
rekram1-node Jul 3, 2026
a9144ec
feat(app): improvements to model search (#34954)
arvsrn Jul 3, 2026
30936a9
chore: generate
opencode-agent[bot] Jul 3, 2026
abaab29
feat(opencode): add code-mode MCP adapter (#35085)
rekram1-node Jul 3, 2026
72845e0
chore: generate
opencode-agent[bot] Jul 3, 2026
41a3cfc
chore: update nix node_modules hashes
opencode-agent[bot] Jul 3, 2026
a4fed69
feat(app): dropdown search fix (#34961)
arvsrn Jul 3, 2026
9aab24e
fix(opencode): provide Observability beneath all route service graphs…
kitlangton Jul 3, 2026
eba0bd0
chore: upgrade turbo (#35173)
jlongster Jul 3, 2026
7d84cb0
feat(stats): add model momentum section
adamdotdevin Jul 3, 2026
2152624
chore: generate
opencode-agent[bot] Jul 3, 2026
33ed95f
fix(core): rewrite replacements while hoisting layers (#35175)
jlongster Jul 3, 2026
1f47bbf
fix(stats): link market share labs
adamdotdevin Jul 3, 2026
1681547
chore: artifacts
adamdotdevin Jul 3, 2026
a09447b
chore: generate
opencode-agent[bot] Jul 3, 2026
39c6dd1
feat(tui): render code-mode execute tool with child calls (#35113)
rekram1-node Jul 3, 2026
27e8e2e
refactor(opencode): fail the execute tool on program failure (#35180)
rekram1-node Jul 3, 2026
911fb70
fix(tui): align execute child calls with task indentation (#35190)
rekram1-node Jul 3, 2026
96d53c6
refactor(core): move path resolve into fs service (#35202)
jlongster Jul 3, 2026
ed6dc87
feat(opencode): gate execute tool behind code mode flag (#35185)
rekram1-node Jul 3, 2026
436cd39
chore: generate
opencode-agent[bot] Jul 3, 2026
b44bc0a
cleanup: tweak compaction prompt (#35220)
opencode-agent[bot] Jul 3, 2026
933dbfd
fix(app): restore unfocused composer typing (#35249)
Hona Jul 3, 2026
8b6a2b1
fix(app): delay initial tab preview (#35266)
opencode-agent[bot] Jul 4, 2026
f63a451
fix(desktop): stabilize esm shim injection (#35270)
Hona Jul 4, 2026
a226767
fix(app): match new session panel corners (#35257)
Hona Jul 4, 2026
7a8e7c8
tui: preserve spinner registration (#35292)
simonklee Jul 4, 2026
bcbbf32
fix(app): use v2 tooltip for prompt context (#35351)
opencode-agent[bot] Jul 4, 2026
709af58
fix(core): stop after declined permissions (#35356)
opencode-agent[bot] Jul 4, 2026
a8983bd
feat(codemode): add OpenAPI tool adapter (#35192)
rekram1-node Jul 4, 2026
1b9b260
chore: generate
opencode-agent[bot] Jul 4, 2026
a12d50e
fix(app): hydrate timeline message parents (#35269)
Hona Jul 5, 2026
476e3fc
chore: generate
opencode-agent[bot] Jul 5, 2026
82db86e
feat(desktop): reopen closed tabs and background tab open (#35010)
usrnk1 Jul 5, 2026
78bca5c
chore: generate
opencode-agent[bot] Jul 5, 2026
7cf8d1c
feat(app): terminal improvements (#34747)
arvsrn Jul 5, 2026
7135bc4
chore: generate
opencode-agent[bot] Jul 5, 2026
efd5f0a
fix(app): preserve timeline selection autoscroll (#35383)
Hona Jul 5, 2026
b7e4f1e
fix: update Feishu community link (#35392)
MrMushrooooom Jul 5, 2026
f14eafe
refactor(codemode): remove generic agent tool (#35417)
rekram1-node Jul 5, 2026
be73f46
refactor(codemode): namespace public types (#35425)
rekram1-node Jul 5, 2026
d3459eb
test(mcp): replace module mocks with real servers (#35450)
rekram1-node Jul 5, 2026
e9f5d34
fix(tui): shorten home tips (#31966)
iamdavidhill Jul 5, 2026
68f225a
fix(provider): preserve OpenRouter small model effort (#35478)
opencode-agent[bot] Jul 5, 2026
2b34df9
fix(mcp): preserve metadata across tool pages (#35439)
rekram1-node Jul 6, 2026
e0ec9be
chore: update nix node_modules hashes
opencode-agent[bot] Jul 6, 2026
d4f7039
fix(codemode): unify catalog signatures (#35452)
rekram1-node Jul 6, 2026
e12cb7f
chore: generate
opencode-agent[bot] Jul 6, 2026
14df88e
fix(app): preserve provider dialog backdrop (#35370)
opencode-agent[bot] Jul 6, 2026
3a149ba
fix(app): optimize large review panes (#35375)
Hona Jul 6, 2026
38bb38e
refactor(app): unify provider connect dialog (#35518)
Brendonovich Jul 6, 2026
377d5d2
fix(app): avoid shortcut settings flash (#35349)
opencode-agent[bot] Jul 6, 2026
7f57d2a
feat(app): show draft server status in titlebar (#35521)
Brendonovich Jul 6, 2026
dffecb6
fix(desktop): gate first launch onboarding (#34930)
Brendonovich Jul 6, 2026
977a40a
chore: generate
opencode-agent[bot] Jul 6, 2026
b0e41ff
fix(app): use selected home project for new sessions (#35530)
Brendonovich Jul 6, 2026
561070f
deps: upgrade OpenTUI to v0.4.3 (#35226)
simonklee Jul 6, 2026
0df44c4
chore: generate
opencode-agent[bot] Jul 6, 2026
eb6ff0c
chore: update nix node_modules hashes
opencode-agent[bot] Jul 6, 2026
d5aa79c
feat(codemode): sync v2 implementation (#35574)
rekram1-node Jul 6, 2026
728e86b
chore: generate
opencode-agent[bot] Jul 6, 2026
203885d
sync release versions for v1.17.14
Jul 6, 2026
6cd5812
chore: merge dev into v2
rekram1-node Jul 6, 2026
451b643
chore: update merge branch with latest dev
rekram1-node Jul 6, 2026
7da1598
chore: update merge branch with latest v2
rekram1-node Jul 6, 2026
16a992c
fix(core): update permission tests for prompt input
rekram1-node Jul 6, 2026
497c665
chore: update merge branch with latest v2
rekram1-node Jul 6, 2026
627c0d0
fix(cli): align prompt attachment contract
rekram1-node Jul 6, 2026
c3b9c9d
feat(data): improved model usage section
adamdotdevin Jul 6, 2026
fc09646
fix(data): refine model trend charts
adamdotdevin Jul 6, 2026
dba0801
chore: generate
opencode-agent[bot] Jul 6, 2026
9c23bc8
chore: update merge branch with latest v2
rekram1-node Jul 6, 2026
b2e819d
test(core): align AISDK fixtures with JSON settings
rekram1-node Jul 6, 2026
26885e7
feat(app): align cmd k menu with v2 styles (#35152)
arvsrn Jul 7, 2026
254a481
fix(config): handle unavailable config directories (#35632)
jlongster Jul 7, 2026
6aff2ee
feat(app): visual improvements (#35134)
arvsrn Jul 7, 2026
9353559
chore: generate
opencode-agent[bot] Jul 7, 2026
2a08f8f
feat(app): reintroduce model context tooltip in model selector (#35087)
arvsrn Jul 7, 2026
0497e8b
chore: generate
opencode-agent[bot] Jul 7, 2026
50374ab
feat(app): change traffic light position, fix sequoia bug (#35081)
arvsrn Jul 7, 2026
ae259d8
fix(app): apply settings themes on select (#35011)
opencode-agent[bot] Jul 7, 2026
64fd7a2
fix(app): persist session tab info (#34934)
Brendonovich Jul 7, 2026
c48b77d
chore: generate
opencode-agent[bot] Jul 7, 2026
c5fe32f
fix(app): show unread for pending questions (#34684)
opencode-agent[bot] Jul 7, 2026
65fd2e5
fix(app): prioritize shortcuts in terminal (#35668)
Brendonovich Jul 7, 2026
39397de
chore: generate
opencode-agent[bot] Jul 7, 2026
516f026
fix(app): hide markdown task markers (#35670)
Brendonovich Jul 7, 2026
ea9fffc
feat(data): redesign model efficiency
adamdotdevin Jul 7, 2026
1c25b2f
chore: generate
opencode-agent[bot] Jul 7, 2026
fd9ee43
fix(core): expand home-relative permission paths (#35737)
StarpTech Jul 7, 2026
888dc67
chore: generate
opencode-agent[bot] Jul 7, 2026
78f85b1
fix(core): ensure relevant files survive compaction (#35636)
opencode-agent[bot] Jul 7, 2026
adf178a
fix(llm): classify zai token limit overflow (#35671)
fengjikui Jul 7, 2026
0b2e870
sync release versions for v1.17.15
Jul 7, 2026
14a5529
feat(data): redesign model peers
adamdotdevin Jul 7, 2026
95013d2
fix(app): keep session routes within layouts (#35842)
Brendonovich Jul 8, 2026
6cfe4bc
fix(app): route new session shortcut through tabs (#35849)
Brendonovich Jul 8, 2026
77429f5
feat(app): sync product translations (#35856)
Hona Jul 8, 2026
5a533e3
feat(stats): add model comparison pages
adamdotdevin Jun 24, 2026
ccd8676
feat(stats): add model comparison home
adamdotdevin Jul 8, 2026
a72c388
chore: generate
opencode-agent[bot] Jul 8, 2026
ecd8be7
zen: grok 4.5
fwang Jul 8, 2026
3a95d56
Merge branch 'dev' of https://github.com/anomalyco/opencode into dev
fwang Jul 8, 2026
fe96d4a
zen: grok 4.5
fwang Jul 8, 2026
24d93cf
chore: update merge branch with latest v2
opencode-agent[bot] Jul 8, 2026
f39bdd8
chore: merge dev into v2
rekram1-node Jul 8, 2026
3618ce3
chore: update merge branch with latest v2
rekram1-node Jul 8, 2026
f95f877
fix(core): watch only git projects (#35957)
opencode-agent[bot] Jul 8, 2026
c291837
chore: update merge branch with latest v2
rekram1-node Jul 8, 2026
05a4733
chore: update merge branch with latest dev
rekram1-node Jul 8, 2026
fe6fbe6
chore: remove duplicate merge artifacts
rekram1-node Jul 8, 2026
ccb6b7c
fix: improve xai cache hit rate (#35970)
rekram1-node Jul 8, 2026
9644a00
chore: generate
opencode-agent[bot] Jul 8, 2026
fff6764
fix(console): update square avatar previews (#35975)
iamdavidhill Jul 8, 2026
c33a201
fix(app): prevent command palette first-open flash (#35858)
opencode-agent[bot] Jul 8, 2026
7550aa4
chore: update nix node_modules hashes
opencode-agent[bot] Jul 8, 2026
62de2b3
feat(app): add inline file browser tabs (#35829)
Hona Jul 8, 2026
824455e
fix(app): load capped review patches (#35633)
Hona Jul 8, 2026
83d633f
fix(app): route legacy drafts to session page (#35808)
Hona Jul 8, 2026
aa52d30
feat(app): persist review state per session (#35488)
Hona Jul 8, 2026
d8a57ee
fix(app): unmount hidden session panes (#35628)
Hona Jul 8, 2026
dd25d14
fix(app): reserve review pane minimum instead of capping chat width a…
Hona Jul 8, 2026
0abbcdd
chore: add missing team members (#35980)
opencode-agent[bot] Jul 8, 2026
1db5c24
fix(opencode): expose Grok reasoning variants (#36017)
rekram1-node Jul 9, 2026
13fa493
feat(desktop): add provider connection tip (#35948)
usrnk1 Jul 9, 2026
7c56319
chore: generate
opencode-agent[bot] Jul 9, 2026
3cd9ee5
feat(app): add composer add menu with draft-preserving commands (#35711)
usrnk1 Jul 9, 2026
a4c17f0
feat(desktop): reveal projects in file manager (#35731)
usrnk1 Jul 9, 2026
353e0ee
chore: generate
opencode-agent[bot] Jul 9, 2026
fb1edc4
chore: update nix node_modules hashes
opencode-agent[bot] Jul 9, 2026
e357c90
sync release versions for v1.17.16
Jul 9, 2026
5cc3a51
feat(app): free model selector (#35707)
arvsrn Jul 9, 2026
ae7d632
feat(app): fix descender clipping (#35950)
arvsrn Jul 9, 2026
4f9207d
feat(app): restyle revert dock for v2 (#35560)
usrnk1 Jul 9, 2026
5c860d4
feat(feat): align sub-agent task rows with v2 design (#35167)
usrnk1 Jul 9, 2026
6b41ae9
chore: generate
opencode-agent[bot] Jul 9, 2026
c6c599b
feat(app): refactor help button and add tabs info popup persistence (…
Brendonovich Jul 9, 2026
3b18c64
chore: generate
opencode-agent[bot] Jul 9, 2026
3bebfe6
chore: update nix node_modules hashes
opencode-agent[bot] Jul 9, 2026
fc9021c
zen: retry on 529
fwang Jul 9, 2026
518772c
Merge branch 'dev' of github.com:anomalyco/opencode into dev
fwang Jul 9, 2026
2e43d41
tweak: adjust variant logic for muse (#36079)
rekram1-node Jul 9, 2026
08096b5
sync release versions for v1.17.17
Jul 9, 2026
b4665a8
feat: add meta muse system prompt (#36122)
rekram1-node Jul 9, 2026
b8374b5
fix(copilot): handle zero billing batch size (#36123)
rekram1-node Jul 9, 2026
c2e019b
sync release versions for v1.17.18
Jul 9, 2026
bbac578
chore: update merge branch with latest v2
rekram1-node Jul 9, 2026
10d9d87
chore: merge dev into v2
rekram1-node Jul 9, 2026
de810c1
test(opencode): suppress removed models.dev fixture type
rekram1-node Jul 9, 2026
158058a
test(opencode): update models.dev fixture types
rekram1-node Jul 9, 2026
5e5aef5
test(opencode): restore models.dev fixture service
rekram1-node Jul 9, 2026
9c6bb4f
fix(app): show tree while opening files (#36018)
Hona Jul 9, 2026
b94e55c
fix(app): align context tokens with usage (#36015)
Hona Jul 9, 2026
13b9e55
fix(ui): sometimes outlines get clipped (#33846)
opencode-agent[bot] Jul 9, 2026
251177d
fix(tui): forward environment to worker (#35925)
opencode-agent[bot] Jul 9, 2026
85ef35d
fix(data): oom crash in stats sync
adamdotdevin Jul 10, 2026
d09d561
chore: generate
opencode-agent[bot] Jul 10, 2026
ea982c3
fix(app): wrap session creation state updates in startTransition (#36…
Brendonovich Jul 10, 2026
01131c7
fix(app): focus input on new session (#36077)
opencode-agent[bot] Jul 10, 2026
c769380
feat(app): visual improvements (#36073)
arvsrn Jul 10, 2026
772e976
fix(app): timeline width jumps around when review panel is open/close…
arvsrn Jul 10, 2026
d0ba538
zen: track openai cache_write_tokens
fwang Jul 10, 2026
8a03fc2
feat(app): extract prompt state and add composer model selection (#36…
Brendonovich Jul 10, 2026
60c8833
feat(stats): update model comparison page
adamdotdevin Jul 10, 2026
08a2a62
fix(data): cut athena stats sync cost
adamdotdevin Jul 10, 2026
7dbfd0b
chore: generate
opencode-agent[bot] Jul 10, 2026
f4faacb
feat(stats): unify comparison cards
adamdotdevin Jul 10, 2026
0340a4f
fix(stats): restore native trackpad scrolling
adamdotdevin Jul 10, 2026
a84151e
fix(stats): restore sticky comparison header
adamdotdevin Jul 10, 2026
1c7f65f
fix(stats): stop comparison overscroll
adamdotdevin Jul 10, 2026
4a1982f
feat(stats): add model comparison radar
adamdotdevin Jul 10, 2026
233f069
feat(stats): add comparison seo pages
adamdotdevin Jul 10, 2026
5df822b
fix(stats): polish comparison details
adamdotdevin Jul 10, 2026
9976269
docs: publish GPT 5.6 Sol, Terra, and Luna model availability and pri…
fwang Jul 10, 2026
7ec1ed7
chore: update merge branch with latest v2
rekram1-node Jul 10, 2026
2799784
chore: merge dev into v2
rekram1-node Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions artifacts/glm52-rise-video/sst-env.d.ts
4 changes: 4 additions & 0 deletions infra/lake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const athenaWorkgroup = new aws.athena.Workgroup("LakeAthenaWorkgroup", {
configuration: {
enforceWorkgroupConfiguration: true,
publishCloudwatchMetricsEnabled: true,
// Athena bills $5/TB scanned; kill any query that would scan more than 2 TB
// so a regression cannot silently burn money. Stats sync full passes scan
// ~250 GB as of 2026-07.
bytesScannedCutoffPerQuery: 2 * 1024 ** 4,
resultConfiguration: {
outputLocation: $interpolate`s3://${athenaResultsBucket.bucket}/`,
},
Expand Down
4 changes: 3 additions & 1 deletion infra/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ export const statSync = new sst.aws.Service("StatsSyncService", {
cluster: lakeCluster,
architecture: "arm64",
cpu: "0.25 vCPU",
memory: "0.5 GB",
// 0.5 GB caused an OOM crash loop: every restart immediately re-ran the 4 Athena
// stats queries (~$5/pass) every ~5 minutes instead of hourly.
memory: "2 GB",
image: {
context: ".",
dockerfile: "packages/stats/server/Dockerfile",
Expand Down
9 changes: 9 additions & 0 deletions packages/app/e2e/regression/review-open-file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ test("opens and searches project files inline", async ({ page }) => {
"opencode.global.dat:layout",
JSON.stringify({ review: { diffStyle: "split", panelOpened: true } }),
)
localStorage.setItem(
"opencode.global.dat:review-panel-v2",
JSON.stringify({ sidebarOpened: false, sidebarWidth: 240, expandMode: "collapse" }),
)
localStorage.setItem(
"opencode.window.browser.dat:tabs",
JSON.stringify([{ type: "session", server, sessionId: sessionID }]),
Expand All @@ -86,13 +90,16 @@ test("opens and searches project files inline", async ({ page }) => {
await expectSessionTitle(page, title)

const panel = page.locator("#review-panel")
const sidebar = panel.locator('[data-slot="session-review-v2-sidebar"]')
const contextButton = page.getByRole("button", { name: "View context usage" })
await contextButton.click()
await expect(panel.getByRole("tab", { name: "Context" })).toHaveAttribute("data-selected", "")
await panel.getByRole("button", { name: "Open file" }).click()
await expect(panel.getByRole("tab", { name: "Open file" })).toHaveAttribute("data-selected", "")
await expect(sidebar).toBeVisible()
await contextButton.click()
await expect(panel.getByRole("tab", { name: "Context" })).toHaveAttribute("data-selected", "")
await expect(sidebar).toHaveCount(0)
await panel.getByRole("button", { name: "Open file" }).click()
const filter = panel.getByRole("combobox", { name: "Filter files" })
await expect(filter).toBeFocused()
Expand All @@ -102,9 +109,11 @@ test("opens and searches project files inline", async ({ page }) => {
await panel.getByRole("button", { name: "README.md" }).click()
await expect(panel.getByRole("tab", { name: "README.md" })).toHaveAttribute("data-selected", "")
await expect(panel.getByText("contents:README.md", { exact: true })).toBeVisible()
await expect(sidebar).toHaveCount(0)

await panel.getByRole("button", { name: "Open file" }).click()
await expect(panel.getByRole("tab", { name: "README.md" })).toHaveCount(0)
await expect(sidebar).toBeVisible()
await filter.fill("nested")
const result = panel.getByRole("option", { name: /nested\.ts/ })
await expect(result).toBeVisible()
Expand Down
228 changes: 228 additions & 0 deletions packages/app/e2e/regression/session-timeline-shell-outline.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { expect, test, type Locator, type Page } from "@playwright/test"
import {
assistantMessage,
setupTimeline,
shell,
textPart,
toolPart,
userMessage,
} from "../performance/timeline-stability/fixture"

for (const deviceScaleFactor of [1.25, 1.5]) {
test(`keeps the shell outline inside a fractionally short virtual row at ${deviceScaleFactor}x`, async ({ page }) => {
const shellID = "prt_shell_outline"
const timeline = await setupTimeline(page, {
messages: [userMessage(), assistantMessage([shell(shellID, "completed", "shell output")])],
settings: { newLayoutDesigns: true, shellToolPartsExpanded: true },
reducedMotion: true,
deviceScaleFactor,
})
const part = page.locator(`[data-timeline-part-id="${shellID}"]`)
const output = part.locator('[data-component="bash-output"]')
const row = page.locator("[data-timeline-key]", { has: part })
await expect(output).toBeVisible()
await timeline.settle()

const geometry = await row.evaluate((element) => {
const output = element.querySelector<HTMLElement>('[data-component="bash-output"]')
if (!output) throw new Error("Shell output is unavailable")
const rowRect = element.getBoundingClientRect()
const outputRect = output.getBoundingClientRect()
// Match a rounded-down measurement at a fractional device-pixel phase.
element.style.height = `${outputRect.bottom - rowRect.top - 0.49}px`
element.style.transform = "translateY(0.25px)"
output.style.setProperty("--v2-border-border-base", "rgb(255, 0, 255)")
output.style.setProperty("background", "rgb(0, 0, 0)", "important")
const style = getComputedStyle(output)
return {
outputWidth: outputRect.width,
outputHeight: outputRect.height,
borderColor: style.borderTopColor,
boxShadow: style.boxShadow,
clipMargin: getComputedStyle(element).overflowClipMargin,
}
})
await timeline.settle()

const clipped = await row.evaluate((element) => {
const output = element.querySelector<HTMLElement>('[data-component="bash-output"]')!
return output.getBoundingClientRect().bottom - element.getBoundingClientRect().bottom
})
expect(clipped).toBeCloseTo(0.49, 1)

expect(await page.evaluate(() => devicePixelRatio)).toBe(deviceScaleFactor)
const edges = await captureCardEdges(page, output)

expect(edges.box.width).toBeCloseTo(geometry.outputWidth, 2)
expect(edges.box.height).toBeCloseTo(geometry.outputHeight, 2)
expect(geometry.borderColor).toBe("rgb(255, 0, 255)")
expect(geometry.boxShadow).toBe("none")
expect(geometry.clipMargin).toBe("0.5px")
expect(edges.magenta.top).toBeGreaterThan(0.75)
expect(edges.magenta.bottom).toBeGreaterThan(0.75)
expect(edges.magenta.vertical).toBeGreaterThanOrEqual(2)
})
}

test("keeps the patch card inside a fractionally short virtual row", async ({ page }) => {
const patchID = "prt_patch_outline"
const file = {
filePath: "src/outline.ts",
relativePath: "src/outline.ts",
type: "update",
additions: 1,
deletions: 1,
before: "const outline = false\n",
after: "const outline = true\n",
}
const timeline = await setupTimeline(page, {
messages: [
userMessage(),
assistantMessage([
toolPart(patchID, "apply_patch", "completed", { files: [file.filePath] }, { metadata: { files: [file] } }),
]),
],
settings: { editToolPartsExpanded: true, newLayoutDesigns: true },
reducedMotion: true,
})
const part = page.locator(`[data-timeline-part-id="${patchID}"]`)
const card = part.locator('[data-component="accordion"][data-scope="apply-patch"]')
const row = page.locator("[data-timeline-key]", { has: part })
await expect(card).toBeVisible()
await timeline.settle()

const geometry = await row.evaluate((element) => {
const card = element.querySelector<HTMLElement>('[data-component="accordion"][data-scope="apply-patch"]')
if (!card) throw new Error("Patch card is unavailable")
const rowRect = element.getBoundingClientRect()
const cardRect = card.getBoundingClientRect()
element.style.height = `${cardRect.bottom - rowRect.top - 0.49}px`
const clipMargin = getComputedStyle(element).overflowClipMargin
const bottom = element.getBoundingClientRect().bottom
return {
overflow: card.getBoundingClientRect().bottom - bottom,
paintOverflow: card.getBoundingClientRect().bottom - bottom - Number.parseFloat(clipMargin),
clipMargin,
cardWidth: cardRect.width,
cardHeight: cardRect.height,
}
})
await timeline.settle()

expect(geometry.overflow).toBeCloseTo(0.49, 1)
expect(geometry.paintOverflow).toBeLessThanOrEqual(0)
const edges = await captureCardEdges(page, card)
expect(edges.box.width).toBeCloseTo(geometry.cardWidth, 2)
expect(edges.box.height).toBeCloseTo(geometry.cardHeight, 2)
expect(edges.luminance.top).toBeLessThan(245)
expect(edges.luminance.bottom).toBeLessThan(245)
expect(Math.abs(edges.luminance.bottom - edges.luminance.top)).toBeLessThan(10)
expect(geometry.clipMargin).toBe("0.5px")
})

test("allows paint rounding for every framed row but not fixed turn gaps", async ({ page }) => {
const secondUserID = "msg_outline_second_user"
await setupTimeline(page, {
messages: [
userMessage(undefined, {
summary: {
diffs: [
{
file: "src/summary.ts",
additions: 1,
deletions: 1,
patch: "@@ -1 +1 @@\n-export const value = 1\n+export const value = 2",
},
],
},
}),
assistantMessage([textPart("prt_outline_text", "Assistant text")]),
userMessage(undefined, { id: secondUserID, created: 1700000010000 }),
assistantMessage([], {
id: "msg_outline_second_assistant",
parentID: secondUserID,
created: 1700000011000,
}),
],
})
await expect(page.locator('[data-timeline-row="DiffSummary"]')).toBeVisible()
await expect(page.locator('[data-timeline-row="TurnGap"]')).toBeVisible()

const rows = await page.locator("[data-timeline-key]").evaluateAll((elements) =>
elements.map((element) => ({
tag: element.querySelector<HTMLElement>("[data-timeline-row]")?.dataset.timelineRow,
clipMargin: getComputedStyle(element).overflowClipMargin,
})),
)
expect(rows.filter((row) => row.tag !== "TurnGap").every((row) => row.clipMargin === "0.5px")).toBe(true)
expect(rows.filter((row) => row.tag === "TurnGap")).toEqual([{ tag: "TurnGap", clipMargin: "0px" }])
})

async function captureCardEdges(page: Page, card: Locator) {
const box = await card.boundingBox()
if (!box) throw new Error("Tool card bounds are unavailable")
const viewport = page.viewportSize()
if (!viewport) throw new Error("Viewport bounds are unavailable")
const screenshot = await page.screenshot()
return page.evaluate(
async ({ source, box, viewport }) => {
const image = new Image()
image.src = source
await image.decode()
const canvas = document.createElement("canvas")
canvas.width = image.naturalWidth
canvas.height = image.naturalHeight
const context = canvas.getContext("2d")
if (!context) throw new Error("2D canvas is unavailable")
context.drawImage(image, 0, 0)
const scale = {
x: image.naturalWidth / viewport.width,
y: image.naturalHeight / viewport.height,
}
const rows = (candidates: number[]) => {
const left = Math.floor((box.x + 8) * scale.x)
const width = Math.floor((box.width - 16) * scale.x)
return candidates.map((row) => {
const pixels = context.getImageData(left, row, width, 1).data
const indexes = Array.from({ length: width }, (_, index) => index * 4)
return {
luminance:
indexes
.map((index) => (pixels[index]! + pixels[index + 1]! + pixels[index + 2]!) / 3)
.reduce((sum, value) => sum + value, 0) / width,
magenta:
indexes.filter((index) => pixels[index]! > 200 && pixels[index + 1]! < 180 && pixels[index + 2]! > 200)
.length / width,
}
})
}
const pixels = context.getImageData(0, 0, image.naturalWidth, image.naturalHeight).data
const columns = new Uint32Array(image.naturalWidth)
for (let index = 0; index < pixels.length; index += 4) {
if (pixels[index]! <= 200 || pixels[index + 1]! >= 180 || pixels[index + 2]! <= 200) continue
columns[(index / 4) % image.naturalWidth] = columns[(index / 4) % image.naturalWidth]! + 1
}
const top = box.y * scale.y
const bottom = (box.y + box.height) * scale.y
const topRows = rows([Math.floor(top) - 1, Math.floor(top), Math.ceil(top)])
const bottomRows = rows([Math.floor(bottom) - 2, Math.floor(bottom) - 1, Math.ceil(bottom) - 1])
return {
box,
luminance: {
top: Math.min(...topRows.map((row) => row.luminance)),
bottom: rows([Math.ceil(bottom) - 1])[0]!.luminance,
},
magenta: {
top: Math.max(...topRows.map((row) => row.magenta)),
bottom: Math.max(...bottomRows.map((row) => row.magenta)),
vertical: Array.from(columns).filter((count) => count > box.height * scale.y * 0.75).length,
},
}
},
{
source: `data:image/png;base64,${screenshot.toString("base64")}`,
viewport,
box,
},
)
}
16 changes: 8 additions & 8 deletions packages/app/src/components/prompt-input.tsx
Loading
Loading