Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
871 commits
Select commit Hold shift + click to select a range
70e01a3
docs(dashboard-agent): state what makes a watch fire, not how to repr…
kathiekiwi Aug 8, 2026
4961415
fix(webapp,dashboard-agent-db): settle read state, the dot and unavai…
kathiekiwi Aug 9, 2026
b8910fe
feat(webapp): let the agent's environment JWT read a queue's own row
kathiekiwi Aug 9, 2026
fcc161f
fix(webapp,dashboard-agent): settle the work count on the chat on scr…
kathiekiwi Aug 9, 2026
c86c2ed
style(webapp): drop an import the chat no longer uses
kathiekiwi Aug 9, 2026
e954d82
fix(webapp): stop a resumed turn navigating the tab that only picked …
kathiekiwi Aug 9, 2026
717a498
feat(webapp): add the agent storybook gallery
kathiekiwi Aug 5, 2026
5f9c08d
chore(webapp): drop the gallery screenshot script
kathiekiwi Aug 5, 2026
f32367e
fix(webapp): point the filtered-runs demo intent at the runs collection
kathiekiwi Aug 6, 2026
e8a6e11
fix(webapp): pin the dismissed prompt in the gallery and drop the dea…
kathiekiwi Aug 6, 2026
e2445f7
fix(webapp): repair the agent gallery's fixtures after the rebase, an…
kathiekiwi Aug 8, 2026
9a19274
test(webapp): let the demo isolation check see side-effect and dynami…
kathiekiwi Aug 8, 2026
3407254
fix(webapp): name only demo resources in the gallery's fixtures
kathiekiwi Aug 8, 2026
217facd
test(webapp): keep the gallery's fixtures out of the demo barrel
kathiekiwi Aug 9, 2026
5755c4a
refactor(webapp): drop the unused isDemoChatId helper
kathiekiwi Aug 9, 2026
57f0762
test(webapp): use a static import in the sweep card test
kathiekiwi Aug 9, 2026
61a3288
fix(webapp): scope the org-creation RBAC check to user-actor tokens
kathiekiwi Aug 9, 2026
8fbbcf0
test(webapp): pin 404-before-403 ordering for capped user-actor tokens
kathiekiwi Aug 9, 2026
7fca9f5
fix(webapp): resolved-watch adoption wording, stored queue name in pa…
kathiekiwi Aug 9, 2026
ecc8998
fix(webapp): replay keeps the recorded watch confirmation; resolved w…
kathiekiwi Aug 9, 2026
0787f0c
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
a91af3b
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
6abbd85
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
637a2bb
test(webapp): pin that an ordinary PAT still passes the PAT-only helper
kathiekiwi Aug 9, 2026
c78eaca
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
3b1ee5e
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
feec862
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
82b93db
fix(webapp): compute answered for view blocks in the base message ren…
kathiekiwi Aug 9, 2026
a72b797
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
8f6826e
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
a27a7af
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
d304c1a
test(webapp): assert the org route never consults a plain PAT ability
kathiekiwi Aug 9, 2026
8f017ec
test(webapp): pin that the disabled org route never consults the toke…
kathiekiwi Aug 9, 2026
49f42de
fix(webapp): allow the org-avatar favicon endpoint in the img-src policy
kathiekiwi Aug 9, 2026
a6782c0
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
8803b8a
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
a4cb3ca
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
edb48d5
fix(webapp): close the queued-reload race and the backslash route escape
kathiekiwi Aug 9, 2026
de84db5
Merge remote-tracking branch 'origin/feat/dashboard-agent-ui' into fe…
kathiekiwi Aug 9, 2026
7bce8f8
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
1df17cf
test(dashboard-agent): accept the prompt-prefix measurement after the…
kathiekiwi Aug 9, 2026
a42ad77
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 9, 2026
a27118c
fix(webapp): drop the watch action button when the turn already propo…
kathiekiwi Aug 9, 2026
3984b5c
fix(webapp): report card keeps its series and links, and the metric g…
kathiekiwi Aug 9, 2026
dbb4d34
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
e4ab0a5
test(webapp): the report block adapter keeps series and links
kathiekiwi Aug 9, 2026
aaa9c9c
Merge remote-tracking branch 'origin/feat/dashboard-agent-ui' into fe…
kathiekiwi Aug 9, 2026
7d34cf4
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
4d695bb
feat(webapp): a user-cancelled watch says so in the chat
kathiekiwi Aug 9, 2026
08871bf
fix(webapp): fit the report metric row at the default panel width
kathiekiwi Aug 9, 2026
acf5a14
fix(webapp): a dead stream with a dangling tool call self-heals from …
kathiekiwi Aug 9, 2026
bf82cce
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
2c8a396
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
1a38ebc
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
df64bec
fix(sdk): chat streams reconnect when the body ends mid-turn
kathiekiwi Aug 9, 2026
dd789e2
fix(sdk): re-earn the reconnect budget on any record and honor abort …
kathiekiwi Aug 9, 2026
4378c69
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
ea98c39
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
3237a77
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
2f3b2ec
fix(webapp): the last-chat key stays org-true and a foreign chat heal…
kathiekiwi Aug 9, 2026
a264213
fix(webapp): lift the finding line text 2px
kathiekiwi Aug 9, 2026
0d2760e
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
955622a
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
f6af05e
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
be99614
fix(webapp): the finding text lifts alone, the label stays with the icon
kathiekiwi Aug 9, 2026
87f1d11
fix(webapp): drop the headline icon 4px
kathiekiwi Aug 9, 2026
cd08d08
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
fcd2107
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
959e8d6
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
df020b1
fix(webapp): finding text sits 2px up, not 4
kathiekiwi Aug 9, 2026
d6e1b4e
fix(webapp): a self-evident finding keeps its line and drops the echo…
kathiekiwi Aug 9, 2026
6fcf1cf
fix(webapp): only the warning headline icon sits lower
kathiekiwi Aug 9, 2026
c40b25d
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 9, 2026
94d671f
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 9, 2026
6f54549
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 9, 2026
709065a
fix(webapp): a delta arrow without a magnitude renders nothing
kathiekiwi Aug 10, 2026
32e5b76
fix(dashboard-agent): the watch offer button closes the turn
kathiekiwi Aug 10, 2026
1d4af38
fix(webapp): a report card that offers watch recovery suppresses the …
kathiekiwi Aug 10, 2026
b603cfb
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 10, 2026
a58b22b
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 10, 2026
5779d5d
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 10, 2026
7ce8bc2
test(dashboard-agent): eval pins the watch offer shape and ordering
kathiekiwi Aug 10, 2026
31e939f
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
730ded1
test(webapp): a collapse to zero renders no arrow
kathiekiwi Aug 10, 2026
6334137
fix(webapp): watch-branch typing after the cross-org and report-offer…
kathiekiwi Aug 10, 2026
8e675a1
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 10, 2026
5d90f56
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 10, 2026
5491ffc
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 10, 2026
94f786c
fix(webapp): chat code blocks render at 12px
kathiekiwi Aug 10, 2026
d1840a2
fix(webapp): revive the code block styling streamdown 2.5 renamed away
kathiekiwi Aug 10, 2026
7789d1f
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 10, 2026
de187d4
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 10, 2026
510830d
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 10, 2026
676aee9
fix(webapp): a watch wake says each fact once
kathiekiwi Aug 10, 2026
2cd73ec
fix(webapp): the wake banner stops restating what the text says
kathiekiwi Aug 10, 2026
41a2f4e
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
44b8128
fix(webapp): the server resolves a watch's queue name, whatever the m…
kathiekiwi Aug 10, 2026
4cfd0a2
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
b73599b
fix(webapp): action rows render at the end of the turn
kathiekiwi Aug 10, 2026
accc651
merge: bring the actions reorder into the watch branch
kathiekiwi Aug 10, 2026
bddae8c
test(webapp): the watches suite stops triggering real batch runs
kathiekiwi Aug 10, 2026
00c210b
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
c3fe17b
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 10, 2026
43deaed
fix(dashboard-agent): a failed batch check keeps the chain alive
kathiekiwi Aug 10, 2026
b7f9bbb
test(webapp): the slot-claim scan survives formatting
kathiekiwi Aug 10, 2026
01ef8fd
fix(webapp): navigation filters speak the run page's language
kathiekiwi Aug 10, 2026
4d9af86
fix(dashboard-agent): navigate_to teaches the run-status vocabulary a…
kathiekiwi Aug 10, 2026
489869e
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows' into…
kathiekiwi Aug 10, 2026
116bfb2
Merge branch 'feat/dashboard-agent-ui' into feat/dashboard-agent-flow…
kathiekiwi Aug 10, 2026
a36b670
Merge branch 'feat/dashboard-agent-flows-watch' into feat/agent-story…
kathiekiwi Aug 10, 2026
5e5772e
test(webapp): the email alert gate refuses when either transport var …
kathiekiwi Aug 10, 2026
69c7b02
test(webapp): report parity matches the de-duplicated untrustworthy l…
kathiekiwi Aug 10, 2026
a81b4fa
Merge remote-tracking branch 'origin/feat/dashboard-agent-ui' into fe…
kathiekiwi Aug 10, 2026
3ccaf93
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
f6c90ec
fix(webapp): lint and env-independence in the watch test suite
kathiekiwi Aug 10, 2026
61c60af
Merge remote-tracking branch 'origin/feat/dashboard-agent-flows-watch…
kathiekiwi Aug 10, 2026
a6ae419
merge: origin/main into dashboard-agent base (resolve report-health)
kathiekiwi Aug 10, 2026
f93f8d6
fix(webapp): detect tables inside a JOIN…ON subquery for query-scope …
kathiekiwi Aug 10, 2026
fb4f0b3
fix(webapp): stop the agent body cap matching a task named dashboard-…
kathiekiwi Aug 10, 2026
bb077d4
fix(dashboard-agent): time out stalled agent HTTP calls
kathiekiwi Aug 10, 2026
28c28e6
fix(webapp): cap report cache TTL to the liveness fresh window
kathiekiwi Aug 10, 2026
aef86b3
fix(webapp): reword the healthy-execution report line to not imply fa…
kathiekiwi Aug 10, 2026
64eaf2f
fix(webapp): return 400 for ai-help with a missing query param
kathiekiwi Aug 10, 2026
35ab0c5
fix(webapp): ceiling a capless user-actor token to read-only on env-J…
kathiekiwi Aug 10, 2026
6cb0631
fix(webapp): clamp an env-JWT's lifetime to the delegated token's expiry
kathiekiwi Aug 10, 2026
e367280
fix(webapp): gate the agent maintenance cron on the agent being confi…
kathiekiwi Aug 10, 2026
3f1eec6
docs(errors-api-e2e): mint the e2e token with an explicit write cap
kathiekiwi Aug 10, 2026
502e1bd
fix(webapp): block remote images in model-authored markdown
kathiekiwi Aug 10, 2026
65c60df
fix(webapp): reject CSP-delimiter characters in the img-src allowlist
kathiekiwi Aug 10, 2026
237f01a
test(webapp): assert report cache TTL stays within the liveness fresh…
kathiekiwi Aug 10, 2026
ca2bacd
merge: base-misc review fixes (M2, M10a, H8, H13, M10r, ai-help, swee…
kathiekiwi Aug 10, 2026
b962949
test(webapp): assert StreamdownRenderer drops remote image src end-to…
kathiekiwi Aug 10, 2026
94c3a47
merge: CSP review fixes (B2 block remote model images, B4 reject CSP …
kathiekiwi Aug 10, 2026
99bbc07
merge: propagate review fixes from feat/dashboard-agent-flows
kathiekiwi Aug 10, 2026
e180df0
merge: propagate review fixes from feat/dashboard-agent-ui
kathiekiwi Aug 10, 2026
41c44b9
fix(webapp): gate the watch maintenance cron on the agent being confi…
kathiekiwi Aug 10, 2026
569fe1c
merge: propagate review fixes from feat/dashboard-agent-flows-watch
kathiekiwi Aug 10, 2026
39ba709
fix(dashboard-agent): fence and cap untrusted free-text in tool results
kathiekiwi Aug 10, 2026
5a83bcb
fix(dashboard-agent): tell the agent fenced tool text is data, not in…
kathiekiwi Aug 10, 2026
bf6872d
fix(dashboard-agent): neutralize fence delimiters in payload and fenc…
kathiekiwi Aug 10, 2026
2e58b36
fix(webapp,cli): cap user-actor token lifetime at 7 days
kathiekiwi Aug 10, 2026
1acb6b8
fix(webapp): bind user-actor tokens to their source PAT
kathiekiwi Aug 10, 2026
c18a073
fix(webapp): give the agent's env JWT a stable rate-limit key
kathiekiwi Aug 10, 2026
1e97712
test(webapp): cover the jwt-actor rate-limit branch, not just the helper
kathiekiwi Aug 10, 2026
a97ada5
fix(webapp): recheck the source PAT against the token's own claim, no…
kathiekiwi Aug 10, 2026
b14c8f3
merge: B3 prompt-injection boundary on tool results
kathiekiwi Aug 10, 2026
d6f67d4
merge: H3 PAT-bound token revocation + 7d ceiling, H9 stable rate-lim…
kathiekiwi Aug 10, 2026
876ed56
feat(webapp,dashboard-agent-db): retain and purge deleted agent chats
kathiekiwi Aug 10, 2026
8506877
merge: propagate wave-2 review fixes from feat/dashboard-agent-flows
kathiekiwi Aug 10, 2026
2d0d954
merge: propagate wave-2 review fixes from feat/dashboard-agent-ui
kathiekiwi Aug 10, 2026
23b03c0
merge: propagate wave-2 review fixes from feat/dashboard-agent-flows-…
kathiekiwi Aug 10, 2026
18379a4
fix(webapp): don't let a failed agent-purge enqueue break org deletion
kathiekiwi Aug 10, 2026
41fdffe
merge: org-delete agent-purge enqueue is best-effort
kathiekiwi Aug 10, 2026
2bcd7eb
merge: propagate org-purge best-effort from feat/dashboard-agent-flows
kathiekiwi Aug 10, 2026
28b8183
merge: propagate org-purge best-effort from feat/dashboard-agent-ui
kathiekiwi Aug 10, 2026
1407cc8
merge: propagate org-purge best-effort from feat/dashboard-agent-flow…
kathiekiwi Aug 10, 2026
d2704fa
fix(dashboard-agent): drop doubled "error" prefix in recurrence watch…
kathiekiwi Aug 10, 2026
70c1092
fix(webapp): keep the stored chat pointer when opening a chat fails t…
kathiekiwi Aug 10, 2026
3977c2d
fix(dashboard-agent): finalize the turn's own message ids from newUIM…
kathiekiwi Aug 10, 2026
bd5f8fd
fix(dashboard-agent-db): scope softDeleteChat by organizationId
kathiekiwi Aug 10, 2026
2932b88
merge: newUIMessages finalize + softDeleteChat org-scope review-comme…
kathiekiwi Aug 10, 2026
83b7f07
merge: openChat chat-pointer transient 5xx review-comment fixes
kathiekiwi Aug 10, 2026
ab7d796
merge: watch-wording shortFingerprint review-comment fixes
kathiekiwi Aug 10, 2026
c0a93b0
merge: propagate review-comment fixes from feat/dashboard-agent-flows
kathiekiwi Aug 10, 2026
8d830a0
merge: propagate review-comment fixes from feat/dashboard-agent-ui
kathiekiwi Aug 10, 2026
1e7600e
merge: propagate review-comment fixes from feat/dashboard-agent-flows…
kathiekiwi Aug 10, 2026
5b6e4d0
fix(webapp): replace a stale running step when a settled transcript i…
kathiekiwi Aug 11, 2026
f15a823
fix(webapp): show the cumulative watch-result count in the grouped toast
kathiekiwi Aug 11, 2026
917c75b
merge: replace stale running step on settled transcript re-read
kathiekiwi Aug 11, 2026
1bc64e0
merge: cumulative watch-result count in grouped toast
kathiekiwi Aug 11, 2026
29ae454
merge: propagate second-pass fixes from feat/dashboard-agent-ui
kathiekiwi Aug 11, 2026
cc576bf
merge: propagate second-pass fixes from feat/dashboard-agent-flows-watch
kathiekiwi Aug 11, 2026
40a610b
chore(server-changes): consolidate the dashboard-agent notes into one
kathiekiwi Aug 11, 2026
a1dc88a
merge: consolidate dashboard-agent server-changes 11 to 1
kathiekiwi Aug 11, 2026
12e04c2
merge: propagate server-changes consolidation from feat/dashboard-age…
kathiekiwi Aug 11, 2026
9687eff
merge: propagate server-changes consolidation from feat/dashboard-age…
kathiekiwi Aug 11, 2026
f0a55cc
merge: propagate server-changes consolidation from feat/dashboard-age…
kathiekiwi Aug 11, 2026
1424441
chore: consolidate this PR's changesets into one
kathiekiwi Aug 11, 2026
fe30aa4
docs(server-changes): restore dropped user-facing dashboard agent points
kathiekiwi Aug 11, 2026
f7dfc90
fix(webapp): stop the project-wide user-actor route 500-ing for claim…
kathiekiwi Aug 11, 2026
32ea4b0
test(webapp): add the recheck export to stale user-actor auth mocks
kathiekiwi Aug 11, 2026
4736a93
merge: add recheck/assertSourcePatActive exports to stale auth test m…
kathiekiwi Aug 11, 2026
db414b7
merge: consolidate PR changesets and restore dropped note points
kathiekiwi Aug 11, 2026
bdf1126
merge: propagate changeset consolidation and note restoration from fe…
kathiekiwi Aug 11, 2026
d34beec
merge: propagate changeset consolidation and note restoration from fe…
kathiekiwi Aug 11, 2026
51bd9c0
merge: propagate changeset consolidation and note restoration from fe…
kathiekiwi Aug 11, 2026
2aeb32f
refactor(webapp): move dashboard-agent render UI to the UI PR
kathiekiwi Aug 11, 2026
635cab2
chore: mark generated drizzle meta as generated
kathiekiwi Aug 11, 2026
f7a7753
merge: propagate base UI relocation + drizzle attribution
kathiekiwi Aug 11, 2026
b046bef
merge: propagate base UI relocation + drizzle attribution
kathiekiwi Aug 11, 2026
81e7b0a
merge: propagate base UI relocation + drizzle attribution
kathiekiwi Aug 11, 2026
24c87c3
test(webapp): assert FROM-less SELECT is valid in the tsql linter
kathiekiwi Aug 11, 2026
4962f7a
test(webapp): update the stale missing-FROM tsql linter case
kathiekiwi Aug 11, 2026
8f8fb98
merge: propagate the tsql linter test fix from feat/dashboard-agent-f…
kathiekiwi Aug 11, 2026
b6b7463
merge: propagate the tsql linter test fix from feat/dashboard-agent-ui
kathiekiwi Aug 11, 2026
ed7a111
merge: propagate the tsql linter test fix from feat/dashboard-agent-f…
kathiekiwi Aug 11, 2026
b2f1d82
test(webapp): move card/winner tests to the UI PR with their render code
kathiekiwi Aug 11, 2026
6a64769
merge: propagate card-test relocation
kathiekiwi Aug 11, 2026
6e4cd37
merge: propagate card-test relocation
kathiekiwi Aug 11, 2026
aeded42
merge: propagate card-test relocation
kathiekiwi Aug 11, 2026
54ab14f
chore: merge main into feat/dashboard-agent-flows
kathiekiwi Aug 11, 2026
eca32d2
chore: merge feat/dashboard-agent-flows (main sync)
kathiekiwi Aug 11, 2026
036b3e5
chore: merge feat/dashboard-agent-ui (main sync)
kathiekiwi Aug 11, 2026
78ea8d8
chore: merge feat/dashboard-agent-flows-watch (main sync)
kathiekiwi Aug 11, 2026
1e7f861
fix(webapp): clear the history-list thinking marker when the streamin…
kathiekiwi Aug 11, 2026
461226d
fix(webapp): make the gallery dismissed-prompts state actually dismis…
kathiekiwi Aug 11, 2026
6b26b28
fix(webapp): stop the grouped watch-updates toast counting wakes the …
kathiekiwi Aug 11, 2026
8023384
chore: merge feat/dashboard-agent-ui (review fixes)
kathiekiwi Aug 11, 2026
a0b605d
chore: merge feat/dashboard-agent-flows-watch (review fixes)
kathiekiwi Aug 11, 2026
dec52bd
chore: merge main into feat/dashboard-agent-ui (post-squash of #4418)
kathiekiwi Aug 11, 2026
eb4f824
fix(webapp): harden model-facing sanitizers, claims resolution and so…
kathiekiwi Aug 11, 2026
8ec976c
chore: merge feat/dashboard-agent-ui (review fixes round 2)
kathiekiwi Aug 11, 2026
cd96f40
chore: merge feat/dashboard-agent-flows-watch (review fixes round 2)
kathiekiwi Aug 11, 2026
a964b09
fix(webapp): keep the draft on Escape and finish polling a died-mid-t…
kathiekiwi Aug 11, 2026
6a33661
fix(webapp): don't mark the open chat unread when the history list re…
kathiekiwi Aug 11, 2026
eeabff0
fix(webapp): use the stored fingerprint form in the demo error watch
kathiekiwi Aug 11, 2026
02d60a4
chore: merge feat/dashboard-agent-ui (review fixes round 3)
kathiekiwi Aug 11, 2026
645895a
chore: merge feat/dashboard-agent-flows-watch (review fixes round 3)
kathiekiwi Aug 11, 2026
843d02b
fix(webapp): let a second Escape close the panel while keeping the fi…
kathiekiwi Aug 11, 2026
a29986b
chore: merge feat/dashboard-agent-ui (composer escape follow-up)
kathiekiwi Aug 11, 2026
3129f72
chore: merge feat/dashboard-agent-flows-watch (composer escape follow…
kathiekiwi Aug 11, 2026
b5c4d1a
chore: merge main into feat/dashboard-agent-flows-watch (post-squash …
kathiekiwi Aug 12, 2026
261a620
chore: merge feat/dashboard-agent-flows-watch (main sync post-#4529)
kathiekiwi Aug 12, 2026
9b6a679
fix(webapp): watch toast plural and container-test hygiene (review)
kathiekiwi Aug 12, 2026
773b43f
fix(dashboard-agent): settle deliveries on chat deletion, accept in-f…
kathiekiwi Aug 12, 2026
ecd293d
chore(webapp,dashboard-agent): review nitpicks — tolerant test assert…
kathiekiwi Aug 12, 2026
3536826
chore: merge review-fix packet (fix(webapp): watch toast plural and c…
kathiekiwi Aug 12, 2026
4a00424
chore: merge review-fix packet (fix(dashboard-agent): settle deliveri…
kathiekiwi Aug 12, 2026
f1f589d
chore: merge review-fix packet (chore(webapp,dashboard-agent): review…
kathiekiwi Aug 12, 2026
3b32417
chore: merge feat/dashboard-agent-flows-watch (review fixes)
kathiekiwi Aug 12, 2026
a696f61
fix(webapp): don't re-send a consumed prompt when switching back to a…
kathiekiwi Aug 12, 2026
2b75a1e
chore: merge review-fix packet (prompt re-send guard)
kathiekiwi Aug 12, 2026
6de38dc
chore: merge feat/dashboard-agent-flows-watch (prompt re-send guard)
kathiekiwi Aug 12, 2026
fa20901
chore: merge main into feat/agent-storybook-gallery (post-squash of #…
kathiekiwi Aug 12, 2026
8cf6099
fix(webapp): let a zero source line reach the URI validator instead o…
kathiekiwi Aug 12, 2026
53d1845
chore: merge review-fix packet (demo line-0 guard)
kathiekiwi Aug 12, 2026
297d6b6
fix(sdk): watch-mode chat subscriptions survive quiet windows (#4548)
kathiekiwi Aug 12, 2026
d0d06c3
fix(webapp): skip the plan-limit cache when billing isn't configured
kathiekiwi Aug 12, 2026
0315232
docs(webapp): scope the watch-limits release note to what's enforced
kathiekiwi Aug 12, 2026
1b3ba21
docs(sdk): note that aborting a resumed subscription no longer stops …
kathiekiwi Aug 12, 2026
4b307dd
fix(webapp): honor a zero message allowance and prefer the server-res…
kathiekiwi Aug 12, 2026
a70c71e
fix(webapp): don't tell paid plans their message allowance was the Fr…
kathiekiwi Aug 12, 2026
6f03c5e
fix(webapp): disable suggestion chips when the message allowance is s…
kathiekiwi Aug 12, 2026
1a2e187
fix(webapp): disable the turn-error retry when the message allowance …
kathiekiwi Aug 12, 2026
c56e3e5
fix(sdk): let a watch subscription re-establish after a reload when t…
kathiekiwi Aug 12, 2026
f15ad15
fix(webapp): release the upgrade panel when the message allowance fre…
kathiekiwi Aug 12, 2026
01eeade
fix(webapp): normalize dashboard-agent message text to well-formed UT…
kathiekiwi Aug 12, 2026
7b07c4f
fix(dashboard-agent): truncate strings without splitting surrogate pairs
kathiekiwi Aug 12, 2026
ac029e5
chore: consolidate release notes
kathiekiwi Aug 12, 2026
f03dfd9
fix(dashboard-agent): normalize message JSON to well-formed UTF-16 at…
kathiekiwi Aug 12, 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
5 changes: 5 additions & 0 deletions .changeset/dashboard-agent-chat-streams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---

Watch-mode chat streams now survive quiet windows and page reloads, and a reply cut off by a lost connection shows an error instead of appearing finished. Aborting a resumed subscription only closes your local stream — call `stopGeneration(chatId)` or pass `stopOnAbort: true` to stop the run. Also fixed a race where quickly restarting a stream could break stop and reconnect, and stopping a chat now hands it back to your other tabs instead of leaving them read-only.
6 changes: 6 additions & 0 deletions .server-changes/agent-plan-limits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
area: webapp
type: feature
---

The dashboard agent now has a monthly message allowance and plan-based limits on watches. Queries stay read-only with clearer errors when busy, and messages with unusual characters no longer fail to send.
13 changes: 7 additions & 6 deletions apps/webapp/app/components/dashboard-agent/AgentUpgradeGate.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { Link } from "@remix-run/react";
import { AgentMonoLogo } from "~/components/primitives/AgentDotMatrix";
import { LinkButton } from "~/components/primitives/Buttons";
import { useOrganization } from "~/hooks/useOrganizations";
import { cn } from "~/utils/cn";
import { v3BillingPath } from "~/utils/pathBuilder";
import { AgentIcon, AGENT_ICON_ACCENT_CLASS, ASK_AGENT_LABEL } from "./agent-identity";
import { ASK_AGENT_LABEL } from "./agent-identity";
import { messageQuotaReachedCopy } from "./message-quota";

// Matches the composer's outer geometry so the replacement lands in the same place.
const SLOT = "flex shrink-0 flex-col bg-background-bright px-3 pb-3 pt-1";

export function AgentUpgradeBlock({
limit,
planResolved,
context,
}: {
limit: number;
planResolved: boolean;
context?: React.ReactNode;
}) {
const organization = useOrganization();
Expand All @@ -22,14 +25,12 @@ export function AgentUpgradeBlock({
{context}
<div className="mt-1.5 flex flex-col gap-2 rounded-md border border-border-bright bg-background-dimmed p-3">
<div className="flex items-center gap-1.5">
<AgentIcon className={cn("size-4 shrink-0", AGENT_ICON_ACCENT_CLASS)} />
<AgentMonoLogo size={16} decorative className="shrink-0" />
<span className="text-sm font-medium text-text-bright">
Upgrade to unlock {ASK_AGENT_LABEL}
</span>
</div>
<p className="text-xs text-text-dimmed">
You've used all {limit} messages included on the Free plan. Your chats stay here to read.
</p>
<p className="text-xs text-text-dimmed">{messageQuotaReachedCopy(limit, planResolved)}</p>
<LinkButton variant="primary/small" to={v3BillingPath(organization)} fullWidth>
Upgrade
</LinkButton>
Expand Down
54 changes: 48 additions & 6 deletions apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import { DashboardAgentContextBanner } from "./DashboardAgentContextBanner";
import { DashboardAgentHero } from "./DashboardAgentHero";
import { DashboardAgentMessages, type TurnActivity } from "./DashboardAgentMessages";
import { MESSAGE_TOO_LARGE_ERROR } from "./message-limits";
import {
FREE_PLAN_MESSAGE_LIMIT,
MESSAGE_QUOTA_REACHED_REASON,
parseQuotaReachedResponse,
type MessageQuota,
} from "./message-quota";
import { createTranscriptOrder, orderTranscript } from "./message-order";
import { navigateDestination } from "./navigate-target";
import { pendingNavigateIntents, pendingWatchIntents } from "./pending-intents";
Expand Down Expand Up @@ -73,6 +79,7 @@ export function DashboardAgentChat({
onCancelWatch,
onTurnSettled,
onActivityChange,
onQuotaChange,
}: {
chatId: string;
initialMessages: UIMessage[];
Expand Down Expand Up @@ -100,8 +107,15 @@ export function DashboardAgentChat({
onCancelWatch: (watchId: string) => void;
onTurnSettled: () => void;
onActivityChange?: (chatId: string, activity: TurnActivity | null) => void;
/** The poll lives here, so this is where the panel learns the cap has lifted. */
onQuotaChange?: (quota: MessageQuota) => void;
}) {
const [input, setInput] = useState("");
// Set when the server refuses a send over the cap, so the block shows at once rather than
// waiting for the next quota poll.
const [quotaReached, setQuotaReached] = useState<{ limit: number; planResolved: boolean } | null>(
null
);
const navigate = useNavigate();
const location = useLocation();
const toast = useToast();
Expand All @@ -128,6 +142,18 @@ export function DashboardAgentChat({
.catch(() => null)) as { error?: string } | null;
throw new Error(data?.error ?? MESSAGE_TOO_LARGE_ERROR);
}
// Over the message cap: show the upgrade block instead of a generic turn error.
if (res.status === 403) {
const data = (await res
.clone()
.json()
.catch(() => null)) as { error?: string; limit?: number } | null;
const reached = parseQuotaReachedResponse(res.status, data);
if (reached) {
setQuotaReached(reached);
throw new Error("You've reached your message limit.");
}
}
return res;
},
clientData,
Expand Down Expand Up @@ -185,9 +211,20 @@ export function DashboardAgentChat({
const orderRef = useRef(createTranscriptOrder(initialMessages));
const messages = orderTranscript(rawMessages, orderRef.current);

// Counted here, not in the panel, so it includes the turn just sent.
const quota = useAgentMessageQuota({ actionPath, chatId, messages });
const atMessageCap = quota.kind === "reached";
// Read here, not in the panel, so it re-reads as each turn settles.
const quota = useAgentMessageQuota({ actionPath, chatId, status });
useEffect(() => {
onQuotaChange?.(quota);
// The quota object is rebuilt every render; only its kind is acted on.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [quota.kind, onQuotaChange]);
// Either the poll saw the cap, or a send was just refused over it.
const atMessageCap = quota.kind === "reached" || quotaReached !== null;
const messageCapLimit =
quotaReached?.limit ?? (quota.kind === "unlimited" ? FREE_PLAN_MESSAGE_LIMIT : quota.limit);
// The poll only runs on the free plan, so its cap is the free-plan nudge; a refusal
// carries the plan limit the server resolved.
const messageCapPlanResolved = quotaReached?.planResolved ?? false;

const isStreaming = status === "streaming";
// From status, not the last part: the indicator must stay up through silent tool calls.
Expand Down Expand Up @@ -252,6 +289,8 @@ export function DashboardAgentChat({
}, [sendRequest, submit, canSend]);

const retry = useCallback(() => {
// Over the cap, a retry only earns another 403 — same guard as `submit`.
if (atMessageCap) return;
// A watch's consent record is a user message nobody typed, so retry never treats it as one.
const action = retryAction(
messages.filter((m) => !(m.role === "user" && isWatchRequestMessageId(m.id)))
Expand All @@ -264,7 +303,7 @@ export function DashboardAgentChat({
return;
}
void sendMessage({ text: action.text, messageId: action.messageId });
}, [messages, sendMessage, regenerate, clearError]);
}, [messages, sendMessage, regenerate, clearError, atMessageCap]);

const resolveUri = useTriggerUriResolver(actionPath);

Expand Down Expand Up @@ -399,13 +438,15 @@ export function DashboardAgentChat({
onSelect={submit}
pageContext={clientData.pageContext}
promoted={promotedPrompt}
promptsDisabledReason={atMessageCap ? MESSAGE_QUOTA_REACHED_REASON : undefined}
/>
) : (
<DashboardAgentMessages
messages={messages}
activity={activity}
error={error}
onRetry={retry}
retryDisabledReason={atMessageCap ? MESSAGE_QUOTA_REACHED_REASON : undefined}
onDismissError={clearError}
onIntent={handleIntent}
pagePaths={pagePaths}
Expand All @@ -414,9 +455,10 @@ export function DashboardAgentChat({
/>
)}
{watchCard ? <div className="px-3 pb-2">{watchCard}</div> : null}
{quota.kind === "reached" ? (
{atMessageCap ? (
<AgentUpgradeBlock
limit={quota.limit}
limit={messageCapLimit}
planResolved={messageCapPlanResolved}
context={
<DashboardAgentContextBanner
projectSlug={projectSlug}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ArrowUpIcon, StopIcon } from "@heroicons/react/20/solid";
import { sliceWellFormed } from "@internal/dashboard-agent-contracts";
import { useEffect, useRef } from "react";
import { Button } from "~/components/primitives/Buttons";
import { cn } from "~/utils/cn";
Expand Down Expand Up @@ -94,7 +95,7 @@ export function DashboardAgentComposer({
maxLength={MAX_MESSAGE_CHARS}
onChange={(e) => {
escapeGuardArmed.current = true;
onChange(e.target.value.slice(0, MAX_MESSAGE_CHARS));
onChange(sliceWellFormed(e.target.value, MAX_MESSAGE_CHARS));
}}
onBlur={() => {
escapeGuardArmed.current = true;
Expand Down
64 changes: 44 additions & 20 deletions apps/webapp/app/components/dashboard-agent/DashboardAgentDraft.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { SuggestedPrompt } from "@internal/dashboard-agent-contracts";
import { useCallback, useMemo, useState } from "react";
import { AgentUpgradeBlock } from "./AgentUpgradeGate";
import { DashboardAgentComposer } from "./DashboardAgentComposer";
import { DashboardAgentContextBanner } from "./DashboardAgentContextBanner";
import { DashboardAgentHero } from "./DashboardAgentHero";
import { MESSAGE_QUOTA_REACHED_REASON } from "./message-quota";
import type { AgentPageContext } from "./page-context-types";
import { readDismissedPromptIds, resolveSuggestedPromptsBySlot } from "./suggested-prompts";

Expand All @@ -16,6 +18,7 @@ export function DashboardAgentDraft({
pageContext,
promotedPrompt,
watchCard,
capReached,
}: {
onSubmit: (text: string) => void;
projectSlug: string;
Expand All @@ -24,6 +27,7 @@ export function DashboardAgentDraft({
pageContext?: AgentPageContext;
promotedPrompt?: SuggestedPrompt;
watchCard?: React.ReactNode;
capReached?: { limit: number; planResolved: boolean } | null;
}) {
const [input, setInput] = useState("");

Expand All @@ -43,39 +47,59 @@ export function DashboardAgentDraft({

const submit = useCallback(
(text: string) => {
// Suggested prompts reach here via the hero, bypassing the composer's cap guard.
if (capReached) return;
const trimmed = text.trim();
if (!trimmed) return;
Comment thread
kathiekiwi marked this conversation as resolved.
setInput("");
onSubmit(trimmed);
},
[onSubmit]
[onSubmit, capReached]
);

return (
<DashboardAgentHero
onSelect={submit}
pageContext={pageContext}
promoted={promotedPrompt}
promptsDisabledReason={capReached ? MESSAGE_QUOTA_REACHED_REASON : undefined}
composer={
<div className="flex w-full flex-col gap-3">
{watchCard}
<DashboardAgentComposer
layout="hero"
value={input}
onChange={setInput}
onSubmit={() => submit(input)}
onStop={() => {}}
isStreaming={false}
placeholderSuggestion={watchCard ? undefined : placeholderSuggestion}
context={
<DashboardAgentContextBanner
projectSlug={projectSlug}
environmentSlug={environmentSlug}
currentPage={currentPage}
/>
}
/>
</div>
capReached ? (
<div className="flex w-full flex-col gap-3">
{watchCard}
<AgentUpgradeBlock
limit={capReached.limit}
planResolved={capReached.planResolved}
context={
<DashboardAgentContextBanner
projectSlug={projectSlug}
environmentSlug={environmentSlug}
currentPage={currentPage}
/>
}
/>
</div>
) : (
<div className="flex w-full flex-col gap-3">
{watchCard}
<DashboardAgentComposer
layout="hero"
value={input}
onChange={setInput}
onSubmit={() => submit(input)}
onStop={() => {}}
isStreaming={false}
placeholderSuggestion={watchCard ? undefined : placeholderSuggestion}
context={
<DashboardAgentContextBanner
projectSlug={projectSlug}
environmentSlug={environmentSlug}
currentPage={currentPage}
/>
}
/>
</div>
)
}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ export function DashboardAgentHero({
promoted,
dismissedIds,
composer,
promptsDisabledReason,
}: {
/** Receives the prompt text to send, not the button label. */
onSelect: (prompt: string) => void;
pageContext?: AgentPageContext;
promoted?: SuggestedPrompt;
dismissedIds?: string[];
composer?: React.ReactNode;
/** Set to disable the suggestion chips and say why. */
promptsDisabledReason?: string;
}) {
// Centred by the child's `m-auto`, not by `justify-center`: auto margins give up their space
// once the content outgrows the panel, so the heading stays scrollable to.
Expand All @@ -40,6 +43,7 @@ export function DashboardAgentHero({
pageContext={pageContext}
promoted={promoted}
dismissedIds={dismissedIds}
disabledReason={promptsDisabledReason}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export type DashboardAgentMessagesProps = {
activity: TurnActivity | null;
error?: Error;
onRetry?: () => void;
/** Set to disable the retry button and say why, e.g. over the message cap. */
retryDisabledReason?: string;
onDismissError?: () => void;
onIntent?: (intent: AgentIntent) => void;
resolveUri?: (uri: string) => ResolvedUri | null;
Expand Down Expand Up @@ -356,6 +358,7 @@ export function DashboardAgentTurns({
activity,
error,
onRetry,
retryDisabledReason,
onDismissError,
onIntent,
resolveUri,
Expand Down Expand Up @@ -402,7 +405,16 @@ export function DashboardAgentTurns({
(onRetry || onDismissError) && (
<ChatActionsRow>
{onRetry && (
<Button variant="primary/small" LeadingIcon={ArrowPathIcon} onClick={onRetry}>
<Button
variant="primary/small"
LeadingIcon={ArrowPathIcon}
onClick={onRetry}
disabled={!!retryDisabledReason}
tooltip={retryDisabledReason}
aria-label={
retryDisabledReason ? `Try again — ${retryDisabledReason}` : undefined
}
>
Try again
</Button>
)}
Expand Down
Loading
Loading