Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
264 commits
Select commit Hold shift + click to select a range
ce8d644
fix(cursor): discover built-in skills in the composer (#24595)
juliusmarminge Oct 25, 2026
97548db
fix(server): retry provider event writes after brief SQLite locks (#2…
juliusmarminge Oct 25, 2026
3eb8366
fix(server): settle inactive threads with persisted open PR links (#2…
juliusmarminge Oct 25, 2026
5848bc2
feat(mobile): Settings is a workspace tab, and tabs never open on an …
juliusmarminge Oct 25, 2026
5cf4995
feat(mobile): the folded Duo opens search from a search tab below the…
juliusmarminge Oct 25, 2026
95ffbc9
revert(mobile): take the folded Duo search tab back out for now (#24626)
juliusmarminge Oct 25, 2026
27805ef
fix(web): preview images outside the workspace (#24627)
juliusmarminge Oct 25, 2026
91ea0e1
fix(threads): Working holds only background work the agent waits on (…
t3dotgg Oct 25, 2026
fa1347d
fix(web): switched threads and Scroll to end land on the real end (#2…
t3dotgg Oct 25, 2026
14b828e
fix(web): attach DNG originals as generic files (#24625)
juliusmarminge Oct 25, 2026
cd2b681
fix(server): surface failed runtime request answer delivery (#24616)
juliusmarminge Oct 25, 2026
b8be6da
fix(preview): report navigation timeout accurately (#24356)
Ethereal49 Oct 25, 2026
945fd1d
fix(web): give PR row metadata room below the title (#24553)
juliusmarminge Oct 25, 2026
5ed8b54
fix(mobile): center floating status actions (#24526)
PixPMusic Oct 25, 2026
453bf01
fix(mobile): the iPhone new-chat button sits beside the tab bar on iO…
wojas Oct 25, 2026
6548c00
fix(web): signed-out T3 Connect shows a Sign in button (#24636)
t3dotgg Oct 25, 2026
62eb35b
perf(mobile): stop menu fault logging and whole-list re-renders on Ho…
juliusmarminge Oct 25, 2026
074d9e4
fix(mobile): preserve syntax and navigation in large diffs (#24276)
juliusmarminge Oct 25, 2026
67c3afb
perf(shell): cold connects skip idle subagent threads, a third of the…
t3dotgg Oct 25, 2026
fb76594
feat: share a thread with a guest who watches live and sends messages…
t3dotgg Oct 25, 2026
2887855
fix(antigravity): say when sign-in cannot reach Google (#24652)
t3dotgg Oct 25, 2026
eabcfa2
fix: canonicalize git.cafe pull request links (#22634)
maria-rcks Oct 25, 2026
edb2b2f
feat(mobile): manage labels, edit PRs and comments, react, and refres…
juliusmarminge Oct 25, 2026
d228f1f
perf(web): highlight code with @pierre/highlights instead of Shiki (#…
maria-rcks Oct 25, 2026
e19fe08
perf(server): thread opens and live events send each message body onc…
t3dotgg Oct 25, 2026
8f26ed7
refactor: halve code comments and cap comment blocks at four lines (#…
maria-rcks Oct 25, 2026
68d5b7a
chore: fit three comments to the four-line cap so lint passes on main…
t3dotgg Oct 25, 2026
24c80f3
fix(claude): ENABLE_TOOL_SEARCH=auto no longer costs 10x cache writes…
t3dotgg Oct 25, 2026
8045537
perf(orchestration): thread snapshots send each long ID once (#24643)
t3dotgg Oct 25, 2026
e666c01
fix(mobile): keep visible diff files highlighted (#24682)
juliusmarminge Oct 25, 2026
8fdaf34
fix(mobile): Settings split view keeps its selection and its header m…
juliusmarminge Oct 25, 2026
90c455f
fix(mobile): every Duo header blurs under the vertical bar, from one …
juliusmarminge Oct 25, 2026
b808f7f
feat(settings): follow-ups steer the running turn by default (#24718)
maria-rcks Oct 25, 2026
a0e0f8a
fix(mobile): Duo threads no longer open shifted left (#24732)
juliusmarminge Oct 25, 2026
c2845de
fix(mobile): PR links open in the app the same way they do on web (#2…
juliusmarminge Oct 25, 2026
e9d6125
feat(web): command palette search finds options inside submenus (#24709)
maria-rcks Oct 25, 2026
8c0670b
fix(mobile): one way to select a page, so split view stops pushing (#…
juliusmarminge Oct 25, 2026
c83342d
fix(mobile): Settings pages no longer flicker when switching beside t…
juliusmarminge Oct 25, 2026
c79ef8c
fix(server): use Codex native collaboration modes (#24737)
t3dotgg Oct 25, 2026
242d00c
fix(clients): threads no longer flash in the inbox before they settle…
t3dotgg Oct 25, 2026
906d1e9
fix(mobile): the iPhone compose icon matches the tab icons' size (#24…
juliusmarminge Oct 25, 2026
a43b003
feat(infra): share Vite task cache with Axiom savings telemetry (#24693)
juliusmarminge Oct 25, 2026
ebd29ca
fix(mobile): screen lists register with their header, enforced by lin…
juliusmarminge Oct 25, 2026
b3d382e
feat(mobile): search Settings, and keep its sidebar header clean (#24…
juliusmarminge Oct 25, 2026
8d3261e
fix(mobile): threads open with less waiting, and the Threads tab reme…
juliusmarminge Oct 25, 2026
15702a9
fix(mobile): reduce diff entry and source highlighting delays (#24770)
juliusmarminge Oct 25, 2026
17dc1af
perf(client): skip unchanged shell and config cache writes (#24266)
juliusmarminge Oct 25, 2026
3e20b65
fix(mobile): remove perpetual reconnect indicator animation (#24273)
juliusmarminge Oct 25, 2026
f694a19
feat(mobile): close the keyboard from the Duo's side bar (#24696)
t3dotgg Oct 25, 2026
cfdfc2a
fix(mobile): dispatch native toolbar actions to current handlers (#24…
juliusmarminge Oct 25, 2026
2da177c
fix(server): PR watch wakes say the PR stays linked and watched (#24781)
t3dotgg Oct 25, 2026
003b64d
feat(server): thread tools return a ready t3-thread link (#24784)
t3dotgg Oct 25, 2026
a96cf08
fix(server): running task results tell the agent to end its turn (#24…
t3dotgg Oct 25, 2026
a8603af
fix(server): mobile push no longer says "completed" between runs (#24…
t3dotgg Oct 25, 2026
e641761
fix(server): delegated children no longer see pull request watch tool…
t3dotgg Oct 25, 2026
5398be0
fix(mobile): search stays open after going back from a thread (#24748)
t3dotgg Oct 25, 2026
e0b1940
feat(server): request_secret can save a CLI token to a private file (…
t3dotgg Oct 25, 2026
639dc20
fix(server): threads settle right after a shell merge of an unlinked …
t3dotgg Oct 25, 2026
5d5b6e0
fix(server): worktree setup no longer hangs when a shell startup prom…
t3dotgg Oct 25, 2026
dca46e2
feat(server): link pull requests agents create from the shell (#24813)
t3dotgg Oct 25, 2026
c8231f9
fix(mobile): queue Steer button no longer opens the editor on a near …
t3dotgg Oct 25, 2026
056b445
fix(usage): Gemini 4 Argon usage from Antigravity now has a price (#2…
t3dotgg Oct 25, 2026
30fd973
fix(server): publish committed events before writer cancellation (#24…
Yash-Singh1 Oct 25, 2026
c916261
fix(web): shared dev servers no longer crash on lazy routes (#24839)
t3dotgg Oct 25, 2026
2d620f5
fix(web): chat tables and subagent rows line up (#24835)
t3dotgg Oct 25, 2026
e57c093
perf(shell): cold connects skip older settled threads, 93% of the she…
t3dotgg Oct 25, 2026
375da0f
test(server): restart replay tests no longer hang on a leftover check…
t3dotgg Oct 25, 2026
3faeb9e
feat(web): Settings and Usage open as large modals over your thread (…
t3dotgg Oct 25, 2026
a6aca34
fix(server): forked threads get titles from the history they inherit …
t3dotgg Oct 25, 2026
d2f6ff4
fix(release): desktop builds pass again after the vite-plus 1.4 upgra…
t3dotgg Oct 25, 2026
5f64c5e
feat(server): cut T3's agent instructions and tool copy by 60% (#24850)
t3dotgg Oct 25, 2026
3d00499
perf(desktop): stop decoding snapshots twice for accessibility (#19221)
AksharP5 Oct 25, 2026
bbdc136
feat(desktop): import cookies from Zen Browser (#22970)
UtkarshUsername Oct 25, 2026
87d22b0
perf(shared): avoid repeated date parsing when selecting PRs (#22891)
UtkarshUsername Oct 25, 2026
5b35402
fix(web): refresh the current branch when opening the picker (#22807)
UtkarshUsername Oct 25, 2026
d0b9e9d
fix(mobile): the Duo header blur reaches a vertical bar on the left t…
juliusmarminge Oct 25, 2026
c5332bf
fix(mobile): stabilize composer search debounce targets (#24272)
juliusmarminge Oct 25, 2026
daa182b
fix(server): surface why process group metrics are not exported (#23969)
yordis Oct 25, 2026
3ed4890
test(mobile): mock threads in the composer search debounce test (#24954)
juliusmarminge Oct 25, 2026
133b9b0
fix(server): serve audio and video from draft workspaces (#24275)
juliusmarminge Oct 25, 2026
8096799
fix(mobile): share toast motion and bring bottom undo to iOS (#23968)
PixPMusic Oct 25, 2026
40ec16a
fix(mobile): the Duo sidebar changes with the rotation, not after it …
juliusmarminge Oct 25, 2026
1eb4071
perf(mobile): append terminal output without replaying history (#24261)
juliusmarminge Oct 25, 2026
550f119
fix(server): attachments are no longer silently dropped from prompts …
maria-rcks Oct 25, 2026
140de68
fix(mobile): images picked with choose files reach the agent as image…
maria-rcks Oct 25, 2026
efea686
feat(web): attach svg files to messages (#21355)
maria-rcks Oct 25, 2026
728aba3
fix(infra): share cache dashboard with the organization
juliusmarminge Oct 25, 2026
532023a
feat(server): send pdf attachments to claude and antigravity as docum…
maria-rcks Oct 25, 2026
7bafc40
feat(mobile): play audio inline and open shared files in the viewer (…
maria-rcks Oct 25, 2026
34e9c56
feat(web): play audio inline and open any file the agent shares in th…
maria-rcks Oct 25, 2026
5d9a5c9
perf(pull-requests): faster pull request timeline, code tab, summary …
maria-rcks Oct 25, 2026
ba006f2
perf(mobile): bound streaming markdown cache and pending work (#24263)
juliusmarminge Oct 25, 2026
d414cb5
fix(web): question options show a radio and an aligned shortcut key (…
maria-rcks Oct 25, 2026
0504c99
fix(server): notify parents after delegated background runs (#23542)
juliusmarminge Oct 25, 2026
557db6c
fix(server): running delegates tell agents to end the turn (#24887)
t3dotgg Oct 25, 2026
aa247c5
perf(ci): cache server tests individually across shards (#24966)
juliusmarminge Oct 25, 2026
94231a0
fix(ci): shorten delegated follow-up comment
juliusmarminge Oct 25, 2026
0191d6c
feat(mobile): one cached native-client install command for agents and…
juliusmarminge Oct 25, 2026
b3b2c55
perf(source-control): pull request previews read only the pull reques…
maria-rcks Oct 25, 2026
e5ed5c5
feat(infra): native client cache panels on the task cache dashboard
juliusmarminge Oct 25, 2026
8b3b2ea
fix(mobile): report native client installs under the fleet machine label
juliusmarminge Oct 25, 2026
0f4d050
feat(infra): native client cache panels on the task cache dashboard (…
juliusmarminge Oct 25, 2026
3816296
feat(web): UI design overhaul, with the new look behind a Beta toggle…
t3dotgg Oct 25, 2026
1a4bb08
test(server): tests no longer depend on the host machine (#25001)
t3dotgg Oct 25, 2026
abd9d9f
perf: opening a thread loads 85% less data (#24899)
t3dotgg Oct 25, 2026
1646a47
fix(server): orchestrator records command count and duration again (#…
yordis Oct 25, 2026
a960f56
fix(observability): every app reports its own environment and release…
yordis Oct 25, 2026
762b047
chore(lint): React effects can't grow past each file's budget (#24964)
juliusmarminge Oct 25, 2026
01fe8d9
fix(observability): every exported resource names its service instanc…
yordis Oct 25, 2026
03d1a90
fix(install): stable installs no longer fail behind a page of nightli…
t3dotgg Oct 25, 2026
e3592ef
fix(server): Grok refresh no longer restores removed models from cach…
t3dotgg Oct 25, 2026
5f1f604
feat(mobile): on-demand chrome e2e runner across simulators
juliusmarminge Oct 25, 2026
2ed9261
fix: restore files reverted by 5f1f604
juliusmarminge Oct 25, 2026
7ee8a5b
fix(server): resume fallback keeps the latest turn when an older hand…
t3dotgg Oct 25, 2026
2fd28bf
fix(client-runtime): "Codex (hub)" badges read CH instead of C( (#22918)
t3dotgg Oct 25, 2026
2050a12
fix(mobile): retain requested PR environment while connecting (#24262)
juliusmarminge Oct 25, 2026
a27b246
fix(web): usage-limit banner reset time follows the Time format setti…
t3dotgg Oct 25, 2026
313ca27
fix(web): terminal drag selection scrolls faster the farther past the…
t3dotgg Oct 25, 2026
20ee805
fix(observability): resources add OTel semconv runtime and browser ke…
yordis Oct 25, 2026
3e69171
fix(knip): mobile-e2e runs agent-device's CLI by path
juliusmarminge Oct 25, 2026
69234b1
chore(lint): main passes lint again with effects merged after the bud…
t3dotgg Oct 25, 2026
725ada6
fix(server): ended roots no longer leave provider turns running (#22846)
t3dotgg Oct 25, 2026
92125d6
feat(mobile): open threads and devices in a resizable iOS inspector (…
juliusmarminge Oct 25, 2026
2dfd6bf
chore(web): measure renders before/after with render scenarios (#24980)
juliusmarminge Oct 25, 2026
b2baf75
fix(web): asset URLs re-mint per revision and before expiry without e…
juliusmarminge Oct 25, 2026
7561c2e
fix(web): queued-message edits survive navigation and settle once (#2…
juliusmarminge Oct 25, 2026
d997763
refactor(mobile): thread visits are tracked outside React (#24973)
juliusmarminge Oct 25, 2026
6016969
refactor(client): cloud account transitions run in one service (#24974)
juliusmarminge Oct 25, 2026
604ecb6
refactor(client): one VCS status refresh owner per checkout (#24975)
juliusmarminge Oct 25, 2026
4ee4788
refactor(web): document appearance and title are applied from app sta…
juliusmarminge Oct 25, 2026
b457b64
refactor(web): app shell shortcuts register once through one command …
juliusmarminge Oct 25, 2026
c6b9c38
refactor(web): shared intersection and document-activity stores (#25020)
juliusmarminge Oct 25, 2026
1c10563
refactor(web): the theme store and diff worker pool stop syncing the …
juliusmarminge Oct 25, 2026
d5b921c
fix(server): keep history discovery off the writer and pace compactio…
JustYannicc Oct 25, 2026
b76a110
perf(mobile): compact persisted thread snapshots (#24265)
juliusmarminge Oct 25, 2026
b6c326d
fix(server): background compactions no longer flip threads to Working…
juliusmarminge Oct 25, 2026
dd2842f
fix(web): a stale queued-edit save no longer clears a newer edit (#25…
juliusmarminge Oct 25, 2026
2649693
fix(client): a thread opened before its shell loads still counts as o…
juliusmarminge Oct 25, 2026
3ddfcfc
docs: open and track PRs through GitCafe when origin is git.cafe (#25…
juliusmarminge Oct 25, 2026
c298a40
perf(web): diff file boundaries observe visibility once instead of on…
juliusmarminge Oct 25, 2026
796fc0a
fix(mobile): center toast actions beside wrapped messages (#24986)
PixPMusic Oct 25, 2026
481b9b7
fix(server): compact superseded turn-item snapshots (#20990)
JustYannicc Oct 25, 2026
3e9d97a
feat(server): count how guest sharing gets used (#24996)
t3dotgg Oct 25, 2026
f898557
chore(lint): enforce unnecessaryPipeChain (#25077)
juliusmarminge Oct 25, 2026
1a13127
test(web): Arabic arrow-key test no longer drops its first key press …
t3dotgg Oct 25, 2026
44df336
fix(mobile): upgrade react-native-keyboard-controller to 1.22.8 for t…
juliusmarminge Oct 26, 2026
2ee1529
fix(infra): keep task cache cleanup ahead of uploads (#25143)
juliusmarminge Oct 26, 2026
0aeb620
chore(lint): enforce mapSomeToAsSome (#25078)
juliusmarminge Oct 26, 2026
05ef5ff
chore(lint): enforce flatMapIgnoredParamToAndThen (#25089)
juliusmarminge Oct 26, 2026
8bdf378
chore(lint): enforce provideLayerSucceedToProvideService (#25090)
juliusmarminge Oct 26, 2026
10d800c
chore(lint): enforce unicorn/require-module-specifiers (#25102)
juliusmarminge Oct 26, 2026
15c6e6b
chore(lint): enforce unicorn/no-useless-fallback-in-spread (#25103)
juliusmarminge Oct 26, 2026
b0f5d44
chore(lint): enforce eslint/no-unneeded-ternary (#25105)
juliusmarminge Oct 26, 2026
2eccc57
chore(lint): enforce eslint/no-unsafe-optional-chaining (#25106)
juliusmarminge Oct 26, 2026
f995643
fix(web): preview favicons resolve their project without ChatView syn…
juliusmarminge Oct 26, 2026
4db2ffc
refactor(mobile): branch picker owns its search and checkout guard (#…
juliusmarminge Oct 26, 2026
65822d8
refactor(web): composer editor stops mirroring props into refs with e…
juliusmarminge Oct 26, 2026
03df289
fix(client): usage-limit Snooze disables at reset even weeks away, vi…
juliusmarminge Oct 26, 2026
738fd08
fix(infra): task cache cleanup test provides its service directly (#2…
juliusmarminge Oct 26, 2026
c58beff
chore(lint): a new React effect states its reason instead of raising …
juliusmarminge Oct 26, 2026
0ad399c
test(web): the diff boundary observer counter lives in its fixture (#…
juliusmarminge Oct 26, 2026
07066c0
fix(client): a queued-edit save keeps its claim until it finishes (#2…
juliusmarminge Oct 26, 2026
5fee09a
refactor(web): terminal focus requests name the terminal they focus (…
juliusmarminge Oct 26, 2026
f4e1407
fix(web): pull request checks stay current after a checks refresh (#2…
juliusmarminge Oct 26, 2026
0b42aa9
chore(devices): bump agent-device to 0.21.31 (#25065)
juliusmarminge Oct 26, 2026
0bf4d16
feat(mobile): composer placeholder reads "Ask anything" (#25176)
flamboh Oct 26, 2026
c8c6deb
refactor(mobile): shared AppState, reduce-motion and back-button help…
juliusmarminge Oct 26, 2026
e14d08c
fix(web): settings panels derive state instead of syncing it with eff…
juliusmarminge Oct 26, 2026
5786e12
refactor(mobile): terminal lifecycle runs in a session store, not scr…
juliusmarminge Oct 26, 2026
9f7b8ad
refactor(web): branch toolbar and dialogs stop syncing through effect…
juliusmarminge Oct 26, 2026
f16ae12
refactor(web): thread find state lives in one store instead of event …
juliusmarminge Oct 26, 2026
9296c20
refactor(web): browser panel tabs follow preview sessions without Cha…
juliusmarminge Oct 26, 2026
11bd26e
chore(lint): enforce effectSucceedWithVoid (#25074)
juliusmarminge Oct 26, 2026
9c02109
chore(lint): enforce preferSucceedSomeOrNone (#25080)
juliusmarminge Oct 26, 2026
312a12d
chore(lint): enforce unnecessaryFailYieldableError (#25083)
juliusmarminge Oct 26, 2026
9ae08d5
chore(lint): enforce catchToOrElseSucceed (#25084)
juliusmarminge Oct 26, 2026
16573c4
chore(lint): enforce allOfMapToForEach (#25085)
juliusmarminge Oct 26, 2026
ef005d6
chore(lint): enforce unnecessaryEffectGen (#25086)
juliusmarminge Oct 26, 2026
f4ba6ae
chore(lint): enforce catchToIgnore (#25087)
juliusmarminge Oct 26, 2026
f5ad87d
chore(lint): enforce optionMatchToFromOption (#25088)
juliusmarminge Oct 26, 2026
a0f3606
chore(lint): enforce redundantMapError (#25091)
juliusmarminge Oct 26, 2026
269deb8
chore(lint): enforce raceFirstWithSleepToTimeout (#25092)
juliusmarminge Oct 26, 2026
686e394
chore(lint): enforce catchUnfailableEffect (#25093)
juliusmarminge Oct 26, 2026
a8b692b
chore(lint): enforce preferTypedSchemaDecoder (#25094)
juliusmarminge Oct 26, 2026
c4dbf19
chore(lint): enforce schemaStructWithTag (#25095)
juliusmarminge Oct 26, 2026
a0b246d
chore(lint): enforce tryCatchInEffectGen (#25097)
juliusmarminge Oct 26, 2026
a320762
chore(lint): enforce eslint/no-unused-vars (#25100)
juliusmarminge Oct 26, 2026
6f21f01
chore(lint): enforce unicorn/no-useless-spread (#25104)
juliusmarminge Oct 26, 2026
3a1b3a7
chore(lint): enforce eslint/no-new (#25107)
juliusmarminge Oct 26, 2026
4e43779
fix(web): theme editor returns to its spot after the window shrinks a…
juliusmarminge Oct 26, 2026
06e80ac
refactor(mobile): cloud account transitions run in the shared account…
juliusmarminge Oct 26, 2026
7a95549
refactor(client): drop the VCS wake and dispatcher element scope opti…
juliusmarminge Oct 26, 2026
d9abfdd
feat(mobile): mobile:install --session installs into an agent-device …
juliusmarminge Oct 26, 2026
888a3d4
fix(server): make document attachments readable to agents (#21458)
maria-rcks Oct 26, 2026
e856833
fix(mobile): native client fingerprints match across macOS and Linux
juliusmarminge Oct 26, 2026
122c5f8
fix(web): keep Windows thread notifications clickable until handled (…
AKolenda Oct 26, 2026
3ca62a5
refactor(client): terminal sessions keep one driver per mode (#25186)
juliusmarminge Oct 26, 2026
b16728a
refactor(web): preview tab sync subscribes to the preview store inste…
juliusmarminge Oct 26, 2026
fe585bc
fix(server): use asSome for initial worktree measurement (#25206)
juliusmarminge Oct 26, 2026
3de45c6
feat(sidebar): working section is on by default (#25190)
maria-rcks Oct 26, 2026
d69810a
feat(web): preview office files, fonts, and mermaid diagrams (#21362)
maria-rcks Oct 26, 2026
73afb57
feat(web): virtualize large file previews (#21466)
maria-rcks Oct 26, 2026
9d17a02
feat(web): preview archives, sqlite databases, and decoded images (#2…
maria-rcks Oct 26, 2026
34ead56
feat(web): preview opendocument, epub, rich text, and notebooks (#21469)
maria-rcks Oct 26, 2026
6700834
chore(lint): enforce eslint/no-empty-pattern (#25101)
juliusmarminge Oct 26, 2026
d19ec7d
chore(lint): enforce typescript/no-extraneous-class (#25108)
juliusmarminge Oct 26, 2026
53896ae
chore(lint): enforce react/capitalized-calls (#25109)
juliusmarminge Oct 26, 2026
fd71ddc
fix(desktop): hidden preview tabs throttle instead of running at full…
t3dotgg Oct 26, 2026
285b19d
chore(lint): enforce react/static-components (#25110)
juliusmarminge Oct 26, 2026
7e20a5b
chore(lint): enforce react/no-unstable-nested-components (#25111)
juliusmarminge Oct 26, 2026
f44fea4
chore(lint): enforce react/no-array-index-key (#25112)
juliusmarminge Oct 26, 2026
908226f
chore(lint): enforce react/immutability (#25115)
juliusmarminge Oct 26, 2026
8a84d40
chore(lint): disable react/jsx-no-constructed-context-values (#25039)
juliusmarminge Oct 26, 2026
c5eb559
chore(lint): disable react/no-object-type-as-default-prop (#25040)
juliusmarminge Oct 26, 2026
56d13e2
chore(lint): disable unicorn/no-array-reverse (#25041)
juliusmarminge Oct 26, 2026
751a37f
chore(lint): disable unicorn/no-new-array (#25042)
juliusmarminge Oct 26, 2026
e5a5515
chore(lint): disable unicorn/prefer-array-find (#25043)
juliusmarminge Oct 26, 2026
78d89dd
chore(lint): disable unicorn/prefer-set-has (#25044)
juliusmarminge Oct 26, 2026
cf21b98
chore(lint): disable unicorn/prefer-string-starts-ends-with (#25045)
juliusmarminge Oct 26, 2026
f10a04b
chore(lint): disable unicorn/prefer-add-event-listener (#25047)
juliusmarminge Oct 26, 2026
d75fb04
chore(lint): disable typescript/no-this-alias (#25048)
juliusmarminge Oct 26, 2026
1cd44f0
chore(lint): disable eslint/no-control-regex (#25049)
juliusmarminge Oct 26, 2026
d1f7018
chore(lint): disable returnEffectInGen (#25050)
juliusmarminge Oct 26, 2026
80b48cc
refactor(mobile): thread detail and feed reset by key and share one f…
juliusmarminge Oct 26, 2026
f88b33a
fix(web): thread find exports the timeline fields type its context na…
juliusmarminge Oct 26, 2026
d487078
chore(lint): enforce react/memo-dependencies (#25117)
juliusmarminge Oct 26, 2026
f279070
fix(web): Escape and copy work in chat media and markdown widgets, wh…
juliusmarminge Oct 26, 2026
f512ff6
fix(web): composer banners, menus and pickers act in their handlers (…
juliusmarminge Oct 26, 2026
0a3b561
refactor(web): device panel reads hub state from atoms (#25265)
juliusmarminge Oct 26, 2026
c3888da
feat(web): New design brings back color where it means something (#25…
t3dotgg Oct 26, 2026
02f4ba7
fix(web): SSH password prompts wait for their dialog, and the app she…
juliusmarminge Oct 26, 2026
d593081
refactor(mobile): settings and usage screens drop sync effects (#25227)
juliusmarminge Oct 26, 2026
a2589f2
fix(mobile): review opens on Changes and keeps the section you picked…
juliusmarminge Oct 26, 2026
7510e5e
fix(mobile): Android dialogs raised before or during activity replace…
juliusmarminge Oct 26, 2026
1de6494
chore(lint): enforce react/purity (#25038)
juliusmarminge Oct 26, 2026
04a21bb
fix(web): app loads again after a chunk cycle blanked it at boot (#25…
t3dotgg Oct 26, 2026
8a4ad94
refactor(web): root notification and toast coordinators start with th…
juliusmarminge Oct 26, 2026
6a3a460
refactor(web): sidebar thread lists derive state instead of syncing i…
juliusmarminge Oct 26, 2026
beeb215
chore(lint): enforce react/refs (#25116)
juliusmarminge Oct 26, 2026
9d6a2e5
fix(web): new thread shortcut focuses palette search, not the Back bu…
t3dotgg Oct 26, 2026
85f17ea
chore(lint): enforce react/exhaustive-effect-dependencies (#25118)
juliusmarminge Oct 26, 2026
72d4dc9
fix(web): composer corners and context strip no longer show double ed…
t3dotgg Oct 26, 2026
f1b8758
fix(web): VS Code icon in thread details no longer has a box around i…
t3dotgg Oct 26, 2026
7df7cb9
fix(web): sent messages stand out on the black canvas in the new desi…
t3dotgg Oct 26, 2026
90ee70b
Merge upstream/main 7df7cb9999 into coder-only
henrychu04 Oct 27, 2026
9ecdf7b
Pin the gateway CSP to upstream's new boot script hash
henrychu04 Oct 27, 2026
36a4686
Restore the run-on-settle switch the merge dropped
henrychu04 Oct 27, 2026
380d481
Pin new transitive packages to upstream's resolved versions
henrychu04 Oct 27, 2026
1e36856
Satisfy knip after the sync
henrychu04 Oct 27, 2026
b1aa611
Document the 7df7cb9999 sync seams and checks
henrychu04 Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .task-cache.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"endpoint": "https://t3-task-cache.pinglabs.workers.dev/projects/t3code"
}
2 changes: 1 addition & 1 deletion apps/coder-gateway/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function sendText(
"Cache-Control": "no-store",
"Content-Type": contentType,
"Content-Security-Policy":
"default-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval' 'sha256-66N88M2Gs4tvXNc8z6k+OKKok8OCKne3d83NpL7KJ9A='; connect-src 'self' blob: https: http: ws://127.0.0.1:*; img-src 'self' data: blob: https: http:; media-src 'self' blob: https: http:; worker-src 'self' blob:; object-src 'self' blob:; frame-src 'self' blob:",
"default-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval' 'sha256-+xUlzIW26WOhLd/WV5CUp/KDzSwFacmCLHCiJxm72Yw='; connect-src 'self' blob: https: http: ws://127.0.0.1:*; img-src 'self' data: blob: https: http:; media-src 'self' blob: https: http:; worker-src 'self' blob:; object-src 'self' blob:; frame-src 'self' blob:",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Cross-Origin-Resource-Policy": "same-origin",
Expand Down
15 changes: 14 additions & 1 deletion apps/coder-helper/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ export const coderHelperStdioLayer = RpcServer.layer(
Layer.provide(Layer.succeed(Logger.LogToStderr)(true)),
);

if (import.meta.main) {
// Coder: upstream's `bin.ts` dispatch for `DocumentText.ts`, which runs office document text
// extraction in a child process of the server's own entry point; here that is the helper bundle.
if (import.meta.main && process.argv[2] === "__document-text") {
const { extractDocumentText } = await import("t3/src/provider/documentTextWorker.ts");
try {
process.stdout.write(await extractDocumentText(process.argv[3]!, process.argv[4]!));
} catch (error) {
if (error instanceof Error && "code" in error && /^E[A-Z0-9]+$/.test(String(error.code))) {
throw error;
}
// Exit 2 identifies document rejections; OS and process failures remain retryable.
process.exitCode = 2;
}
} else if (import.meta.main) {
Layer.launch(coderHelperStdioLayer).pipe(NodeRuntime.runMain);
}
6 changes: 1 addition & 5 deletions apps/server/integration/SqlStatementCounter.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ export interface SqlStatementCounter {
readonly count: () => number;
}

/**
* Install the same counter on every runtime under test, otherwise statements
* run by background reactors and statements run by request handlers land in
* different counters.
*/
/** Install on every test runtime to include background reactor statements. */
export function makeSqlStatementCounter(): SqlStatementCounter {
let statements = 0;
const tracer = Tracer.make({
Expand Down
49 changes: 47 additions & 2 deletions apps/server/integration/transferBudgetV2.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import {
EnvironmentAuthenticatedPrincipal,
ORCHESTRATION_V2_WS_METHODS,
OrchestrationV2RpcSchemas,
OrchestrationV2ThreadBoundedSnapshot,
OrchestrationV2ThreadDetailSnapshot,
OrchestrationV2ThreadHistoryPage,
OrchestrationV2ShellSnapshot,
OrchestrationV2GetThreadProjectionError,
OrchestrationV2GetShellSnapshotError,
Expand Down Expand Up @@ -63,11 +65,23 @@ import {
type TransferBudgetRun,
} from "./TransferBudgetReport.integration.ts";
import { TRANSFER_HISTORY_TURN_COUNT } from "./fixtures/transferBudget.ts";
import { THREAD_ID, threadCreated, turnEvents } from "./TransferBudgetV2Fixture.integration.ts";
import {
LONG_TURN_THREAD_ID,
longTurnThreadBatches,
THREAD_ID,
threadCreated,
turnEvents,
} from "./TransferBudgetV2Fixture.integration.ts";

const decodeThreadSnapshot = Schema.decodeUnknownEffect(
Schema.fromJsonString(Schema.toCodecJson(OrchestrationV2ThreadDetailSnapshot)),
);
const decodeBoundedSnapshot = Schema.decodeUnknownEffect(
Schema.fromJsonString(Schema.toCodecJson(OrchestrationV2ThreadBoundedSnapshot)),
);
const decodeHistoryPage = Schema.decodeUnknownEffect(
Schema.fromJsonString(Schema.toCodecJson(OrchestrationV2ThreadHistoryPage)),
);
const decodeShellSnapshot = Schema.decodeUnknownEffect(
Schema.fromJsonString(Schema.toCodecJson(OrchestrationV2ShellSnapshot)),
);
Expand All @@ -87,6 +101,10 @@ const layerManagement = Layer.unwrap(
getThreadSnapshot: (id) => projections.getThreadSnapshot(id).pipe(Effect.orDie),
getThreadSnapshotWindow: (id, options) =>
projections.getThreadSnapshotWindow(id, options).pipe(Effect.orDie),
getThreadHistoryPage: (id, cursor, throughEntryId, conversationOnly) =>
projections
.getThreadHistoryPage(id, cursor, throughEntryId, conversationOnly)
.pipe(Effect.orDie),
getThreadShell: (id) => projections.getThreadShell(id).pipe(Effect.orDie),
getShellSnapshot: (options) => projections.getShellSnapshot(options).pipe(Effect.orDie),
listActiveSubagentThreadIds: () =>
Expand Down Expand Up @@ -331,7 +349,29 @@ it.live("reports V2 thread HTTP and WebSocket transfer budgets", () =>
const shellMode = yield* synchronized(rsq);
const reconnectThread = { ...resumedThread.recorder.totals(), mode: threadMode };
const reconnectShell = { ...resumedShell.recorder.totals(), mode: shellMode };
const reconnectSqlStatements = counter.count() - reconnectSqlStart;
assert.equal(threadMode, "snapshot");

for (const events of longTurnThreadBatches(provider)) yield* sink.write({ events });
const longTurnColdOpen = yield* measureHttpGet({
url: `${base}/api/orchestration/threads/${LONG_TURN_THREAD_ID}/bounded?compactTurnItems=1`,
headers: { [ORCHESTRATION_PROTOCOL_HEADER]: String(ORCHESTRATION_PROTOCOL_VERSION) },
});
assert.equal(longTurnColdOpen.status, 200);
const coldOpen = yield* decodeBoundedSnapshot(
Buffer.from(longTurnColdOpen.decodedBody).toString(),
);
const cursor = coldOpen.historyCursor;
if (cursor === null) return yield* Effect.die("Expected older long-turn history");
const longTurnHistoryPage = yield* measureHttpGet({
url: `${base}/api/orchestration/threads/${LONG_TURN_THREAD_ID}/history?cursor=${encodeURIComponent(cursor)}`,
headers: { [ORCHESTRATION_PROTOCOL_HEADER]: String(ORCHESTRATION_PROTOCOL_VERSION) },
});
assert.equal(longTurnHistoryPage.status, 200);
const historyPage = yield* decodeHistoryPage(
Buffer.from(longTurnHistoryPage.decodedBody).toString(),
);
assert.isTrue(historyPage.hasMoreHistory);
return {
provider,
threadSnapshot,
Expand All @@ -342,7 +382,12 @@ it.live("reports V2 thread HTTP and WebSocket transfer budgets", () =>
measuredTurnSqlStatements,
reconnectThread,
reconnectShell,
reconnectSqlStatements: counter.count() - reconnectSqlStart,
reconnectSqlStatements,
longTurnColdOpen: {
http: longTurnColdOpen,
rows: coldOpen.projection.visibleTurnItems.length,
},
longTurnHistoryPage: { http: longTurnHistoryPage, rows: historyPage.items.length },
} satisfies TransferBudgetRun;
}).pipe(
Effect.provide(Layer.fresh(layerServices).pipe(Layer.provideMerge(NodeServices.layer))),
Expand Down
6 changes: 5 additions & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
"@t3tools/source-control-core": "workspace:*",
"@t3tools/source-control-definitions": "workspace:*",
"@t3tools/source-control-gitlab": "workspace:*",
"character-entities": "2.0.2",
"effect": "catalog:",
"node-pty": "1.2.0-beta.15",
"saxes": "6.0.0",
"stream-chain": "^4.2.5",
"stream-json": "3.6.0",
"yaml": "catalog:"
"yaml": "catalog:",
"yauzl": "^3.4.0"
},
"devDependencies": {
"@anthropic-ai/claude-agent-sdk": "0.3.276",
Expand All @@ -33,6 +36,7 @@
"@t3tools/shared": "workspace:*",
"@t3tools/source-control-testing": "workspace:*",
"@types/node": "catalog:",
"@types/yauzl": "^3.4.0",
"effect-acp": "workspace:*",
"effect-codex-app-server": "workspace:*",
"vite-plus": "catalog:"
Expand Down
166 changes: 140 additions & 26 deletions apps/server/scripts/acp-mock-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const emitGrokMonitorPostTurnPoll = process.env.T3_ACP_EMIT_GROK_MONITOR_POST_TU
const emitGrokBackgroundTaskStarted = process.env.T3_ACP_EMIT_GROK_BACKGROUND_TASK_STARTED === "1";
const emitGrokBackgroundTaskPoll = process.env.T3_ACP_GROK_BACKGROUND_TASK_COMPLETION === "poll";
const emitForeignSessionUpdates = process.env.T3_ACP_EMIT_FOREIGN_SESSION_UPDATES === "1";
const omitInitializeModelState = process.env.T3_ACP_OMIT_INITIALIZE_MODEL_STATE === "1";
const waitForResumeRelease = process.env.T3_ACP_WAIT_FOR_RESUME_RELEASE === "1";
const completeFirstPromptOnCancel = process.env.T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL === "1";
const floodStderr = process.env.T3_ACP_FLOOD_STDERR === "1";
Expand Down Expand Up @@ -429,8 +430,7 @@ function modeState(): AcpCompat.SessionModeState {
};
}

// Mirrors the real Grok ACP: it advertises versioned model ids, never the CLI's own
// "grok-build" product name.
// Grok ACP advertises versioned model ids, never the CLI product name.
const grokAcpModels: ReadonlyArray<AcpCompat.ModelInfo> = [
{
modelId: process.env.T3_ACP_GROK_MODEL ?? "grok-4.6",
Expand Down Expand Up @@ -576,7 +576,7 @@ const program = Effect.gen(function* () {
return {
protocolVersion: 2,
info: { name: "t3-acp-mock-agent", version: "0.0.0" },
_meta: { modelState: modelState() },
...(omitInitializeModelState ? {} : { _meta: { modelState: modelState() } }),
capabilities: {
session: {
...(supportsSessionLifecycle ? { fork: {}, additionalDirectories: {} } : {}),
Expand All @@ -600,8 +600,7 @@ const program = Effect.gen(function* () {
}),
);

// Mirrors the real Antigravity agent: the API key method reads
// GEMINI_API_KEY from the process environment and rejects when it is missing.
// Antigravity requires GEMINI_API_KEY for API key authentication.
yield* agent.handleAuthenticate((request) =>
Effect.gen(function* () {
if (antigravityProfile) {
Expand Down Expand Up @@ -938,21 +937,20 @@ const program = Effect.gen(function* () {
},
});
});
yield* Effect.sleep("1200 millis")
.pipe(
Effect.andThen(
Effect.sync(() => {
writeJsonRpcNotification("_x.ai/task_completed", {
sessionId: cancelledSessionId,
update: {
sessionUpdate: "task_completed",
task_snapshot: { task_id: "task-bg-1", command: "sleep 30" },
},
});
}),
),
)
.pipe(Effect.forkDetach);
yield* Effect.sleep("1200 millis").pipe(
Effect.andThen(
Effect.sync(() => {
writeJsonRpcNotification("_x.ai/task_completed", {
sessionId: cancelledSessionId,
update: {
sessionUpdate: "task_completed",
task_snapshot: { task_id: "task-bg-1", command: "sleep 30" },
},
});
}),
),
Effect.forkDetach,
);
}
}),
);
Expand All @@ -962,6 +960,124 @@ const program = Effect.gen(function* () {
const requestedSessionId = String(request.sessionId ?? sessionId);
beginAcpMockPrompt(cancelledSessions, requestedSessionId);
promptCount += 1;
const idleError = process.env.T3_ACP_IDLE_ERROR;
if (idleError === "grok-background" && promptCount === 1) {
// The structured completion lands before the prompt settles, so it is buffered.
const taskId = "call-idle-error-background";
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call",
toolCallId: taskId,
title: "run_terminal_command",
kind: "execute",
status: "in_progress",
rawInput: { command: "sleep 1; echo done" },
},
});
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call_update",
toolCallId: taskId,
status: "completed",
rawOutput: {
type: "BackgroundTaskStarted",
task_id: taskId,
task_type: "bash",
status: "running",
command: "sleep 1; echo done",
},
},
});
writeJsonRpcNotification("_x.ai/task_completed", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "task_completed",
task_snapshot: { task_id: taskId, kind: "bash", exit_code: 0, output: "done\n" },
},
});
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: { sessionUpdate: "state_update", state: "idle", stopReason: "error" },
});
return {};
}
if (idleError !== undefined && promptCount === 1) {
const toolCallId = "tool-call-idle-error-1";
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call_update",
toolCallId,
title: "Terminal",
kind: "execute",
status: "in_progress",
rawInput: { command: ["long-running-tool"] },
},
});
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call_update",
toolCallId: "tool-call-idle-error-monitor",
title: "Monitor",
kind: "execute",
status: "in_progress",
rawInput: { command: ["background-monitor"] },
},
});
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call_update",
toolCallId: "tool-call-idle-error-subagent",
title: "Subagent",
kind: "other",
status: "in_progress",
rawInput: {},
},
});
writeJsonRpcNotification("session/update", {
sessionId: "mock-child-session-idle-error",
update: {
sessionUpdate: "tool_call_update",
toolCallId: "tool-call-idle-error-child",
title: "Child tool",
kind: "execute",
status: "in_progress",
rawInput: { command: ["child-tool"] },
},
});
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "state_update",
state: "idle",
stopReason: "error",
...(idleError === "details"
? { error: { code: -32000, message: "Missing Authentication header" } }
: {}),
},
});
// The agent outlives the failed prompt, so its subagent finishes afterwards.
yield* Effect.sleep("50 millis").pipe(
Effect.andThen(
Effect.sync(() =>
writeJsonRpcNotification("session/update", {
sessionId: requestedSessionId,
update: {
sessionUpdate: "tool_call_update",
toolCallId: "tool-call-idle-error-subagent",
status: "completed",
},
}),
),
),
Effect.forkDetach,
);
return {};
}
if (
process.env.T3_ACP_CRASH_PROMPT === "1" &&
request.prompt.some((part) => part.type === "text" && part.text === "crash now")
Expand Down Expand Up @@ -1464,11 +1580,9 @@ const program = Effect.gen(function* () {
const detachedCommand = runningCommandIgnoresTerm
? 'trap "" TERM; bash -c \'trap "" TERM; while :; do sleep 1; done\' & child=$!; printf "%s %s %s\n" "$PPID" "$$" "$child" > "$1"; echo published; wait "$child"'
: 'sleep 120 & child=$!; printf "%s %s %s\n" "$PPID" "$$" "$child" > "$1"; echo published; wait "$child"';
// Nested bash publishes "$PPID $$ $child" once it starts. Do not
// write the launcher PID alone here: that races with bash and can
// clobber the triple that interrupt tests wait for. It then prints a
// line, so an agent that exits after launch only exits once the
// triple exists instead of racing a slow launcher start.
// Only nested bash writes the "$PPID $$ $child" triple; writing the launcher PID
// here would race it. The launcher's printed line keeps the agent alive until the
// triple exists.
const detachedLauncher = NodeChildProcess.spawn(
process.execPath,
["-e", launcher, "bash", "-c", detachedCommand, "bash", runningCommandPidPath],
Expand Down Expand Up @@ -2322,7 +2436,7 @@ const program = Effect.gen(function* () {
}

if (emitXAiPlanMdWrite) {
// Match Grok's real session layout so isGrokPlanMarkdownPath accepts it.
// isGrokPlanMarkdownPath requires Grok's session layout.
const planRoot = process.env.T3_ACP_PLAN_ROOT ?? "/tmp/mock-home/.grok";
const planPath = `${planRoot}/sessions/${requestedSessionId}/plan.md`;
const planBody = "# Mock plan\n\n- Write the feature\n- Add a test\n- Ship it\n";
Expand Down
Loading