-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(webapp): dashboard agent — chat, reports, investigate #4418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kathiekiwi
wants to merge
481
commits into
main
Choose a base branch
from
feat/dashboard-agent-flows
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+26,000
−3,097
Open
Changes from all commits
Commits
Show all changes
481 commits
Select commit
Hold shift + click to select a range
8e71546
fix(webapp): wake toast and unread dot show with the panel open too
kathiekiwi 4802e81
fix(webapp): the unread dot skips the chat that's on screen
kathiekiwi a8ed165
fix(webapp): Investigate button wears the chat's magnifier; queue pag…
kathiekiwi e69e13e
fix(webapp): queue page button order Period-Investigate-Watch-Overrid…
kathiekiwi a9fe736
fix(webapp): Watch button tooltip defaults to the recommendation's note
kathiekiwi a65c460
fix(webapp): Watch tooltip in the Investigate form — 'Get notified wh…
kathiekiwi 4e392c3
fix(dashboard-agent): prompt pins TRQL columns to snake_case for char…
kathiekiwi 767b754
fix(dashboard-agent): the runs time column is triggered_at — correct …
kathiekiwi 1417064
fix(webapp): settle investigation cards left in progress between turns
kathiekiwi 52cb895
chore(webapp): drop unused import flagged by lint
kathiekiwi 7a70045
feat(dashboard-agent): validate chart queries when render_view runs
kathiekiwi c858b25
fix(webapp): trigger:// links in prose resolve to dashboard paths
kathiekiwi f20eef3
feat(dashboard-agent): the agent offers a watch when its answer point…
kathiekiwi f22310a
fix(dashboard-agent): the watch offer is mandatory when the answer's …
kathiekiwi 2030c33
fix(webapp): agent badges keep their tone colour on system themes
kathiekiwi 97a8e16
feat(dashboard-agent): the watch offer becomes a button
kathiekiwi 39e9ed3
fix(webapp): the agent callout (wake toast) dresses like the Ask Trig…
kathiekiwi f928fb0
feat(webapp): agent status for the standard toast; wake toast uses it
kathiekiwi 0a05d3a
chore(webapp): storybook button to fire the agent toast
kathiekiwi d5ec3d4
chore(webapp): drop the unused agent callout variant; fix a renamed g…
kathiekiwi 6172c7f
fix(webapp): storybook toast page double-mounted a second Toaster
kathiekiwi e19049b
fix(webapp): Toaster inherits the app theme
kathiekiwi 12cdc67
fix(webapp): closing the agent panel drops fullscreen — reopen is alw…
kathiekiwi 6c8e5ef
fix(webapp): watch card confirms with one Watch button, no Done colla…
kathiekiwi 0c39e7a
fix(webapp): run inspector Watch button goes primary, matching Invest…
kathiekiwi 4aa9abc
fix(webapp): wake toasts fire on delivery, not unread state; agent to…
kathiekiwi 93c4a02
feat(webapp): a consented watch investigation conducts itself
kathiekiwi d5d821d
fix(webapp): chat access is organization-scoped everywhere
kathiekiwi 6650b94
fix(webapp): switching organizations resets the open panel
kathiekiwi 555b77e
refactor(webapp): split the agent gallery into pages and prune its st…
kathiekiwi 17758f7
chore(webapp): drop the section-id label from gallery tiles
kathiekiwi 70559be
fix(webapp): attribute env-authed API calls to the acting user (TRI-1…
kathiekiwi b9033f3
fix(webapp): the wake-toast dedupe survives reloads
kathiekiwi 2e01a49
fix(webapp): primary popover trigger keeps white ink on the light theme
kathiekiwi 3ed1c1f
fix(webapp): name the tenant on the dashboard agent routes' failure p…
kathiekiwi cca0d53
chore(webapp): drop the seeder's --heartbeat stand mode
kathiekiwi 7b16385
feat(webapp): a scenario kit for the Watch and Investigate flows
kathiekiwi 331f80e
fix(webapp): watches container tests follow the org-scoped chat queri…
kathiekiwi 2b5a705
fix(webapp): the tick re-authorization user read moves off the replica
kathiekiwi e740c16
fix(webapp): give the remix build the same heap headroom as typecheck
kathiekiwi ef65f46
chore: one release note for the dashboard agent, one short changeset
kathiekiwi 75aba7f
feat(webapp): the scenario kit runs against any local project and env…
kathiekiwi 95fa1b6
chore(webapp): drop the agent-examples review seeder
kathiekiwi 814b527
docs(dashboard-agent): one guidebook replaces the playbook and scenarios
kathiekiwi 1bc6a01
perf(webapp): the wake feed reads a tenant-scoped partial index
kathiekiwi 0045062
perf(webapp): the wake poll sleeps in hidden tabs and no longer runs …
kathiekiwi 0b66440
perf(webapp): a finished report is reusable for 90s
kathiekiwi 4606b94
feat(webapp): the watch sweep retires watches that ended a week ago
kathiekiwi 37e4c23
fix(webapp): the chat name is on the row before the turn settles
kathiekiwi d3d33a6
chore: oxfmt the generated drizzle snapshot and the presenter test im…
kathiekiwi ac1fdfd
chore(dashboard-agent): say why the title gate is the transcript length
kathiekiwi 4dedd60
chore: drop the working notes and the stray diff from the repo root
kathiekiwi cbeee67
feat(dashboard-agent): a batch chain registry, one per environment an…
kathiekiwi e16320b
feat(dashboard-agent): one tick run per environment and cadence, not …
kathiekiwi 5d90eb1
feat(webapp): the batch check answers a whole environment's watches a…
kathiekiwi 3993381
test(dashboard-agent): the batch tick isolates, bounds, and never dou…
kathiekiwi 93c5344
test(webapp): the batch check shares one authorization and one report…
kathiekiwi 1989336
fix(dashboard-agent): a dead chain is re-armed on its own cadence, an…
kathiekiwi a4cd475
chore(webapp): drop the unused stale-window import from the watch sweep
kathiekiwi f428759
chore(dashboard-agent): drop the M0 verdicts file, inline its reasons…
kathiekiwi 8349bf4
chore(webapp): shorten the agent logo, spinner and scenario-kit comments
kathiekiwi 27a9263
chore(webapp): tighten the chat-prose theme comments
kathiekiwi 16682d5
chore(webapp): the page-context comments say only what the handle doe…
kathiekiwi 5247a00
chore(dashboard-agent-db): shorten the query-layer and schema comments
kathiekiwi 398e8c5
chore(dashboard-agent): shorten the watch-tick comments to their inva…
kathiekiwi 0357d79
chore(dashboard-agent-contracts): cut the wire-contract comments to t…
kathiekiwi d1fff9c
chore(webapp): shorten the agent panel and view comments
kathiekiwi 6ac4214
chore(webapp): shorten the suggested-prompt and demo-fixture comments
kathiekiwi a5dd3f1
chore(webapp): shorten the report, waiting-run and agent route comments
kathiekiwi c331843
chore(webapp): shorten the watch service and test comments
kathiekiwi d70bcfc
chore(dashboard-agent): shorten the agent and tool-layer comments
kathiekiwi 0468776
chore: oxfmt the blank lines left by the removed comments
kathiekiwi a303cb0
refactor(webapp): one presenter for all watch and view-block wording
kathiekiwi 1af895b
fix(dashboard-agent): keep a failed turn in the conversation
kathiekiwi 5aef047
fix(webapp): cap the query API's scope at the credential's environment
kathiekiwi 547ec71
feat(webapp): declare the report layout once, shared by the card and …
kathiekiwi f6865d5
feat(webapp): render the markdown and ANSI report from the shared layout
kathiekiwi 880d94a
feat(webapp): build the report card from the shared layout
kathiekiwi 78aea57
test(webapp): assert the card and the text report stay one report
kathiekiwi b062490
chore: add a server-changes note for the report layout parity
kathiekiwi f3237de
chore(webapp): drop the unused demo report card
kathiekiwi 17e11c7
chore(webapp): cut the chat-layout header and stop the test asserting…
kathiekiwi bd6835f
chore(webapp): drop the page-context notes from the route files
kathiekiwi cb70b83
chore(webapp): drop the prose from the chat markdown css rules
kathiekiwi 0d415c0
chore(webapp): strip the step narration from the agent and report tests
kathiekiwi 93bc6c1
chore(webapp): clear the demo fixture and storybook commentary
kathiekiwi 0739337
chore: cut the report, waiting-run and package comments to their facts
kathiekiwi a4f8ed1
chore(webapp): trim the seed-script narration
kathiekiwi e6ec1d2
chore(webapp): delete the agent panel and view rationale comments
kathiekiwi 9b7ca8c
chore: bring the last three-line comments down to two
kathiekiwi 5153cca
chore: restore the comments an off-by-one over-trimmed
kathiekiwi 42749c9
chore(dashboard-agent): cut the agent, tool and watch-tick comments t…
kathiekiwi 9270caf
chore(webapp): cut the watch service and route comments to their inva…
kathiekiwi f9eb9c0
chore(dashboard-agent-db,contracts): cut the query and wire-contract …
kathiekiwi 8d3676a
chore: oxfmt the lines the removed comments let collapse
kathiekiwi 5800e89
chore: drop the unrendered demo cards and fold the release notes back…
kathiekiwi 3773f31
fix(webapp): route the report's stale-data badge through AgentBadge
kathiekiwi fd83288
fix(webapp): drop the metric sparkline to its own line on a narrow panel
kathiekiwi 9b32bfd
fix(webapp): let agent chips follow the interface-contrast control
kathiekiwi 5a80876
fix(webapp): ring the unread dot against the navbar surface
kathiekiwi 3f85acc
fix(webapp): give the diagnosis card links a focus ring via a TextLin…
kathiekiwi 0760f1b
refactor(webapp): give the agent cards one card primitive
kathiekiwi a7a29f3
chore: add a server-changes note for the report card fixes
kathiekiwi d4f0357
chore(webapp): move the gallery's transcripts into the storybook fixt…
kathiekiwi 6a6fa1f
chore: keep the release notes as one
kathiekiwi 02debc6
perf(dashboard-agent): sample a tenth of turns for the judge by default
kathiekiwi dd1f309
perf(dashboard-agent): cap the judge's tool payload and stop pretty-p…
kathiekiwi 7850289
perf(dashboard-agent): stop echoing the panel's view model back to th…
kathiekiwi e8d35fa
perf(dashboard-agent): cap read_file at 48KB / 1500 lines
kathiekiwi 893b9e8
chore(dashboard-agent): oxfmt
kathiekiwi 9b4e473
perf(dashboard-agent): share one 1h-TTL prompt cache between head sta…
kathiekiwi fc4381d
fix(webapp): keep the agent wake poll to one chain per tab
kathiekiwi e109a24
fix(webapp): read the alert channel and the watch target on the primary
kathiekiwi d26a28b
perf(webapp): only poll the wake feed for a browser that knows a watc…
kathiekiwi 1dd8536
perf(webapp): answer the wake poll with one narrow read per database
kathiekiwi 8b042be
perf(webapp): skip the admin read on the watch authorization path
kathiekiwi be1cb04
perf(dashboard-agent-db): index the open investigations the sweep scans
kathiekiwi cafd920
chore: keep the release notes as one
kathiekiwi a88228c
chore(webapp): move the agent storybook gallery out to a follow-up
kathiekiwi b6ebe55
fix(dashboard-agent): escape the prefix separator so the file reviews…
kathiekiwi 5b5a258
fix(webapp): scope a delegated user-actor token to the environment it…
kathiekiwi d6debe8
test(webapp): cover the user-actor token's environment scope on every…
kathiekiwi 30ec754
refactor(dashboard-agent-db): move the watch queries into their own m…
kathiekiwi 2ed5d52
refactor(dashboard-agent-db): move the watch tables into their own sc…
kathiekiwi 46290d1
refactor(dashboard-agent): move the watch wake and investigate lanes …
kathiekiwi 18dffa6
refactor(dashboard-agent): give the watch tests their own file
kathiekiwi a0d06e4
fix(webapp): send the agent wake signal to a browser that has never o…
kathiekiwi ebad471
fix(webapp): cap the size of a message to the agent
kathiekiwi c3ee6a4
perf(webapp): resolve the agent card's links in one request
kathiekiwi 08dc7ba
fix(webapp): keep the watch card in step with its draft, and frozen w…
kathiekiwi 7f13add
feat(webapp): retire judged-turn rows after 30 days
kathiekiwi 42ddcff
feat(dashboard-agent): keep customer data out of the judged-turn row …
kathiekiwi 3c5b2d5
feat(dashboard-agent): never judge a turn that read source
kathiekiwi a4b4ef1
feat(webapp): let an organization turn off judging of its agent turns
kathiekiwi 263b324
feat(dashboard-agent): give the golden runs their own eval sample rate
kathiekiwi 99b8933
docs(dashboard-agent): make the eval docs match the code
kathiekiwi 29d9a8e
chore: note the conversation scoring in the release note
kathiekiwi 31698fa
refactor(dashboard-agent): split the tool set into one module per res…
kathiekiwi fea1a29
refactor(dashboard-agent): split the watch tick into delivery, condit…
kathiekiwi 4876e07
refactor(webapp): give each watch condition family its own module
kathiekiwi fc32fc6
refactor(webapp): split the suggested-prompt registry by responsibility
kathiekiwi f963614
chore(webapp): restore the dashboard agent's flag gate
kathiekiwi 99850ac
feat(dashboard-agent): summarise an oversized conversation, keeping l…
kathiekiwi 1d083f3
test(dashboard-agent): budget the real prompt prefix with ceilings an…
kathiekiwi 42a76fb
perf(dashboard-agent): say a settled watch outcome without a model, a…
kathiekiwi 0c41a70
perf(dashboard-agent): cap search_docs to a few short excerpts
kathiekiwi 6c993f2
chore: note the summarised long conversations in the release note
kathiekiwi ddc6d25
fix(dashboard-agent): describe a value at the redaction depth cap ins…
kathiekiwi 4e39228
fix(dashboard-agent): pin only a live investigation into a compacted …
kathiekiwi a3be7bd
fix(dashboard-agent): cap the output of the summariser and the wake n…
kathiekiwi e599f12
fix(dashboard-agent): rotate an over-cap watch group instead of starv…
kathiekiwi d719c9b
fix(webapp): start the wake poll for a browser that has only an activ…
kathiekiwi 28b1f38
fix(webapp): cap the agent's request body while it streams, not after
kathiekiwi 49a9538
fix(webapp): record a watch request before the watch starts, and repa…
kathiekiwi cbc2edc
test(webapp): pin the watch submit's ordering, its retry repair and i…
kathiekiwi 4ff8859
fix(webapp): keep the agent's alert delete to channels the watch type…
kathiekiwi 50fd10b
fix(webapp): replay a watch submission's recorded outcome instead of …
kathiekiwi 1cdf1f0
refactor(webapp): split the dashboard agent's maintenance cron along …
kathiekiwi 62b598d
docs(webapp): say which layer refuses an oversized agent body
kathiekiwi 85b98ab
fix(webapp): mint the agent's token for the caller's own environment,…
kathiekiwi f5a146b
fix(webapp): cap the agent's body on any method and on a mixed-case path
kathiekiwi 880bf60
test(tsql): pin that no mutating query can pass the query boundary
kathiekiwi 9d45284
fix(webapp): keep the agent token's environment claim on the actor th…
kathiekiwi d51cb9a
fix(webapp): stop the OSS fallback handing a delegated token blanket …
kathiekiwi f58a9dc
fix(webapp): only let the browser set the agent's page context
kathiekiwi d12e6a8
style(webapp): merge duplicate imports on the user-actor auth path
kathiekiwi d2511bd
fix(webapp): hand the sweep's final check the previous facts
kathiekiwi e485209
perf(webapp): resolve the sweep's authorization and readers once per …
kathiekiwi bd2559a
fix(webapp): record only a real evaluation from a batch tick
kathiekiwi 4846cf8
fix(dashboard-agent): finish a wake in the transcript, or don't count it
kathiekiwi 012ce0d
test(webapp): drop an unsafe optional chain from the sweep boundary test
kathiekiwi 5f2f5fe
fix(webapp): scope the watch submission ledger and its alerts to one …
kathiekiwi 5176e3e
test(webapp): pin the watch ledger's tenancy, the once-only alert and…
kathiekiwi a63708c
test(webapp): assert the derived chat id before the submit outcome
kathiekiwi a0640ba
style(webapp): format the watch tenancy changes
kathiekiwi dd90b6e
fix(webapp): never render an image the agent's model authored
kathiekiwi 94ec67f
perf(webapp): keep the agent transcript's investigation winners stable
kathiekiwi 1aee9ca
fix(webapp): send the eval judge only the turn's structural facts
kathiekiwi 488621e
perf(webapp): cache the agent's accumulated tool results between steps
kathiekiwi 32553b9
style(webapp): format the agent markdown test
kathiekiwi d9ff853
style(webapp): format the agent eval and step-cache tests
kathiekiwi 82f4a73
style(webapp): drop a needless escape in the image regex
kathiekiwi 933aeb9
test(webapp): stub the agent proxy's environment lookup, not a Prisma…
kathiekiwi 05b3472
Merge branch 'main' into feat/dashboard-agent-flows
kathiekiwi d73f3f5
chore: ignore the agent worktrees directory
kathiekiwi 48d0d4a
fix(webapp): drop the img-src wildcard host for a validated origin al…
kathiekiwi cd112ba
test(webapp): assert the document img-src has no wildcard host
kathiekiwi 5adba81
docs: document CSP_IMG_SRC_ALLOWLIST for self-hosted image hosts
kathiekiwi fb99526
feat(dashboard-agent): tell the eval judge a failure's kind without i…
kathiekiwi 9daa8f9
docs(dashboard-agent): tell the judge the error category is derived, …
kathiekiwi 09d1b55
fix(webapp): require the watch card's request id instead of falling b…
kathiekiwi 22bf6d9
fix(webapp): cancel the watch a losing submit's winner does not name
kathiekiwi 210863e
fix(webapp): separate a watch's last look from its last check in the …
kathiekiwi 240799d
chore(dashboard-agent): drop the comments the code already says
kathiekiwi 478b30c
chore(dashboard-agent): drop the test comments the assertions already…
kathiekiwi 4e00b79
style(webapp): format the sweep's authorization helper
kathiekiwi d00b126
fix(webapp): bind a delegated token's environment claim on the projec…
kathiekiwi a7fc406
fix(webapp): keep a delegated token's claims on the authenticated ide…
kathiekiwi f700174
fix(webapp): ceiling an exchanged environment JWT by what the delegat…
kathiekiwi 3336a47
test(webapp): give the container-backed user-actor scope tests their …
kathiekiwi 7a645e5
chore(webapp): drop the comments the code already says
kathiekiwi 79482de
chore(webapp): drop the comments the tests already say
kathiekiwi d646809
chore(rbac): keep the delegated-token invariant, drop the essay
kathiekiwi c4d3f58
fix(webapp): replay a watch submission's recorded email outcome inste…
kathiekiwi 49e8fb5
fix(webapp): tell a watch's creator about their own email alerts, not…
kathiekiwi 7b2f9c6
chore(dashboard-agent-db): drop the submission's external-notificatio…
kathiekiwi f7b8374
fix(webapp): put a turn's settled investigation card in the transcript
kathiekiwi 26f93da
fix(webapp): have the stale-investigation sweep close the card it set…
kathiekiwi 07b83da
docs: note the agent's closed investigations, watch email honesty and…
kathiekiwi 60a9584
test(webapp): fail if a route sets an over-broad image CSP
kathiekiwi e62d8c6
style(webapp): format the route image CSP audit
kathiekiwi 1759618
fix(webapp): keep the project-wide answer for an environment-agnostic…
kathiekiwi 657f11d
docs(webapp): say which UAT flow the project-wide answer is preserved…
kathiekiwi 29de34f
style(webapp): drop the imports the merge left unused
kathiekiwi 5bf3612
fix(webapp): settle an investigation and its closing card in one write
kathiekiwi 37c56aa
test(webapp): pin the settlement failure window and the open panel
kathiekiwi 44b4e57
docs: say the investigation card closes while the panel is open
kathiekiwi 49a1504
docs: cut the release note back to what a user notices
kathiekiwi 2e23a09
fix(webapp): keep the other Anthropic options when the step breakpoin…
kathiekiwi f6f753c
fix(webapp): merge the transcript under the row lock instead of repla…
kathiekiwi afc0cfa
fix(webapp): close a consented watch investigation's card atomically
kathiekiwi d52c224
fix(dashboard-agent): merge the step breakpoint into the message's an…
kathiekiwi abaeebb
fix(webapp): make a repeated watch card close leave the revision alone
kathiekiwi c3f4ba8
refactor(webapp): drop the unused settleOpenInvestigations
kathiekiwi 7ab35df
fix(webapp): merge the turn's cache breakpoint into the last message'…
kathiekiwi 020dad2
refactor(webapp): store the dashboard agent's transcript one row per …
kathiekiwi 81e8349
refactor(webapp): drop the dashboard agent's JSONB transcript column
kathiekiwi 398a298
test(webapp): cover the batch position allocator with concurrent turns
kathiekiwi aad8498
fix(webapp): converge the watch transcript when a retried delivery fi…
kathiekiwi d8fda07
fix(webapp): stop an ordinary transcript write from rewriting a store…
kathiekiwi f159c69
test(webapp): guard against a raw-SQL reference to the dropped chats.…
kathiekiwi ceaa38d
fix(webapp): scope the watch transcript's appends to the caller's org…
kathiekiwi 3d3c962
fix(webapp): keep a malformed message's own text out of the error, an…
kathiekiwi e3fcc20
refactor(dashboard-agent-db): collapse the agent's migrations into one
kathiekiwi f4337f7
style(dashboard-agent-db): format the generated migration snapshot
kathiekiwi bb036f9
feat(webapp): split Watch out of the dashboard agent's first PR
kathiekiwi 9fad665
test(webapp): cover the dashboard agent's eval-policy gate, and requi…
kathiekiwi c37bdf8
test(webapp): pin the delegated token's scope ceiling on the RBAC fal…
kathiekiwi 5edfd78
feat(webapp): name the dashboard agent Ask Trigger everywhere
kathiekiwi c88a448
refactor(webapp): rename the ask-ai button variant to ask-trigger
kathiekiwi 0d3d216
feat(webapp): drop the agent button from the deploy blank states
kathiekiwi 9c6f148
chore(webapp): keep Ask AI in the tree, deprecated and unmounted
kathiekiwi db9f9a2
Merge remote-tracking branch 'origin/main' into feat/dashboard-agent-…
kathiekiwi dfcee8b
fix(webapp): settle the API keys route after merging main
kathiekiwi 49051f5
fix(dashboard-agent-db): stop rewriting the published migration history
kathiekiwi 798fdf9
refactor(webapp): split the dashboard agent's UI out of the first PR
kathiekiwi c025bbf
fix(dashboard-agent): keep the finished answer in the transcript, not…
kathiekiwi 2ff7ec0
fix(dashboard-agent): name a head-started chat instead of leaving it …
kathiekiwi 711b79e
fix(dashboard-agent): apply the token's cap as a second ceiling, and …
kathiekiwi c236601
feat(webapp): let an environment JWT read a queue, as it already read…
kathiekiwi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "@trigger.dev/core": patch | ||
| "trigger.dev": patch | ||
| --- | ||
|
|
||
| Reports can be fetched as structured data with the `json` format. The shortest report period is now one minute (`30m`, `1h`, `7d`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --- | ||
| area: webapp | ||
| type: feature | ||
| --- | ||
|
|
||
| Meet the dashboard agent: a chat in every environment that answers questions about your runs, queues, errors and health with real data and links. It takes over from Ask AI everywhere that used to appear; on the Free plan you get 20 messages. | ||
|
|
||
| **Investigate** on a failed run, an error, a backed-up queue or a run that hasn't started gets you a worked-through answer — what happened, why, and how to fix it, with every claim linked to the runs, errors and deploys behind it. | ||
|
|
||
| The health report reads the same everywhere — dashboard, terminal, editor. A very long chat keeps working: the agent summarises the earlier part and carries on. The agent's replies no longer show images. | ||
|
|
||
| A sample of conversations is scored automatically so the agent keeps getting better. Only the score and a one-line summary are kept, never your messages, data or code, and we can switch it off for your organization on request. | ||
|
|
||
| Separately: a queue's wait times, peak depth, throughput and throttling can now be read from the API, and the Docs button has been removed from page headers. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
apps/webapp/app/components/dashboard-agent/message-limits.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| import { describe, expect, it } from "vitest"; | ||
| import { | ||
| checkMessageParts, | ||
| declaredBodyBytes, | ||
| exceedsMessageBodyBytes, | ||
| MAX_MESSAGE_BODY_BYTES, | ||
| MAX_MESSAGE_CHARS, | ||
| MAX_MESSAGE_PARTS, | ||
| } from "./message-limits"; | ||
|
|
||
| describe("message limits", () => { | ||
| it("lets a long real question through", () => { | ||
| const text = "why did this fail?\n".repeat(50); | ||
|
|
||
| expect(exceedsMessageBodyBytes(Buffer.byteLength(text, "utf8"))).toBe(false); | ||
| expect(checkMessageParts([{ type: "text", text }])).toBeNull(); | ||
| }); | ||
|
|
||
| it("refuses a pasted dump by bytes", () => { | ||
| expect(exceedsMessageBodyBytes(MAX_MESSAGE_BODY_BYTES)).toBe(false); | ||
| expect(exceedsMessageBodyBytes(MAX_MESSAGE_BODY_BYTES + 1)).toBe(true); | ||
| }); | ||
|
|
||
| it("counts multi-byte characters as bytes, not characters", () => { | ||
| // Under the char cap, over the byte cap: 4 bytes each. | ||
| const emoji = "🙂".repeat(MAX_MESSAGE_BODY_BYTES / 4 + 1); | ||
|
|
||
| expect(emoji.length).toBeLessThan(MAX_MESSAGE_BODY_BYTES); | ||
| expect(exceedsMessageBodyBytes(Buffer.byteLength(emoji, "utf8"))).toBe(true); | ||
| }); | ||
|
|
||
| it("refuses a dump split across parts", () => { | ||
| const parts = Array.from({ length: 4 }, () => ({ | ||
| type: "text", | ||
| text: "x".repeat(MAX_MESSAGE_CHARS / 2), | ||
| })); | ||
|
|
||
| expect(checkMessageParts(parts)).toBe("too_long"); | ||
| }); | ||
|
|
||
| it("refuses too many parts", () => { | ||
| const parts = Array.from({ length: MAX_MESSAGE_PARTS + 1 }, () => ({ | ||
| type: "text", | ||
| text: "x", | ||
| })); | ||
|
|
||
| expect(checkMessageParts(parts)).toBe("too_many_parts"); | ||
| expect(checkMessageParts(parts.slice(0, MAX_MESSAGE_PARTS))).toBeNull(); | ||
| }); | ||
|
|
||
| it("leaves a shape that isn't a parts array to the schema", () => { | ||
| expect(checkMessageParts(undefined)).toBeNull(); | ||
| expect(checkMessageParts("nope")).toBeNull(); | ||
| }); | ||
|
|
||
| it("reads the declared size, or nothing when it isn't declared", () => { | ||
| expect(declaredBodyBytes(new Headers({ "content-length": "1234" }))).toBe(1234); | ||
| expect(declaredBodyBytes(new Headers())).toBeNull(); | ||
| expect(declaredBodyBytes(new Headers({ "content-length": "nope" }))).toBeNull(); | ||
| // An undeclared size can't be refused here; the body's own length is. | ||
| expect(exceedsMessageBodyBytes(null)).toBe(false); | ||
| }); | ||
| }); |
51 changes: 51 additions & 0 deletions
51
apps/webapp/app/components/dashboard-agent/message-limits.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /** | ||
| * Caps on one message to the agent, shared by the composer and the two server paths a message | ||
| * can arrive through. Generous for a real question with a pasted stack trace, stingy for a dump: | ||
| * an unbounded paste is a large model bill and a permanently fat transcript. | ||
| */ | ||
|
|
||
| /** ~2 pages of text, or a long stack trace. */ | ||
| export const MAX_MESSAGE_CHARS = 8_000; | ||
|
|
||
| /** The counter only shows near the limit, so a normal message never sees it. */ | ||
| export const MESSAGE_CHARS_WARN_AT = Math.floor(MAX_MESSAGE_CHARS * 0.9); | ||
|
|
||
| /** A composed message is a handful of parts; dozens means something is wrong. */ | ||
| export const MAX_MESSAGE_PARTS = 20; | ||
|
|
||
| /** | ||
| * The whole request body, in bytes: headroom for {@link MAX_MESSAGE_CHARS} of any script plus | ||
| * the per-turn metadata, and nothing like a pasted file. | ||
| */ | ||
| export const MAX_MESSAGE_BODY_BYTES = 64 * 1024; | ||
|
|
||
| export const MESSAGE_TOO_LARGE_CODE = "message_too_large"; | ||
|
|
||
| export const MESSAGE_TOO_LARGE_ERROR = "That message is too long. Shorten it and send again."; | ||
|
|
||
| export type MessagePartsProblem = "too_many_parts" | "too_long"; | ||
|
|
||
| /** Counts the parts and their text. Anything that isn't a parts array is left to the schema. */ | ||
| export function checkMessageParts(parts: unknown): MessagePartsProblem | null { | ||
| if (!Array.isArray(parts)) return null; | ||
| if (parts.length > MAX_MESSAGE_PARTS) return "too_many_parts"; | ||
|
|
||
| let chars = 0; | ||
| for (const part of parts) { | ||
| const text = (part as { text?: unknown } | null)?.text; | ||
| if (typeof text === "string") chars += text.length; | ||
| } | ||
| return chars > MAX_MESSAGE_CHARS ? "too_long" : null; | ||
| } | ||
|
|
||
| /** The declared body size, or null when the client didn't declare one. */ | ||
| export function declaredBodyBytes(headers: Headers): number | null { | ||
| const raw = headers.get("content-length"); | ||
| if (!raw) return null; | ||
| const bytes = Number.parseInt(raw, 10); | ||
| return Number.isFinite(bytes) ? bytes : null; | ||
| } | ||
|
|
||
| export function exceedsMessageBodyBytes(bytes: number | null | undefined): boolean { | ||
| return typeof bytes === "number" && bytes > MAX_MESSAGE_BODY_BYTES; | ||
| } |
32 changes: 32 additions & 0 deletions
32
apps/webapp/app/components/dashboard-agent/resolve-uris.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { describe, expect, it } from "vitest"; | ||
| import { MAX_URIS_PER_RESOLVE_REQUEST, planUriBatches } from "./resolve-uris"; | ||
|
|
||
| const uri = (index: number) => `trigger://runs/run_${index}`; | ||
|
|
||
| describe("planUriBatches", () => { | ||
| it("resolves a card's twenty citations in one request", () => { | ||
| const batches = planUriBatches(Array.from({ length: 20 }, (_, index) => uri(index))); | ||
|
|
||
| expect(batches).toHaveLength(1); | ||
| expect(batches[0]).toHaveLength(20); | ||
| }); | ||
|
|
||
| it("asks about each URI once", () => { | ||
| const batches = planUriBatches([uri(1), uri(1), uri(2)]); | ||
|
|
||
| expect(batches).toEqual([[uri(1), uri(2)]]); | ||
| }); | ||
|
|
||
| it("caps a request and carries the rest over", () => { | ||
| const count = MAX_URIS_PER_RESOLVE_REQUEST + 3; | ||
| const batches = planUriBatches(Array.from({ length: count }, (_, index) => uri(index))); | ||
|
|
||
| expect(batches).toHaveLength(2); | ||
| expect(batches[0]).toHaveLength(MAX_URIS_PER_RESOLVE_REQUEST); | ||
| expect(batches[1]).toHaveLength(3); | ||
| }); | ||
|
|
||
| it("has nothing to send for nothing", () => { | ||
| expect(planUriBatches([])).toEqual([]); | ||
| }); | ||
| }); |
25 changes: 25 additions & 0 deletions
25
apps/webapp/app/components/dashboard-agent/resolve-uris.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /** | ||
| * Batching for `trigger://` resolution. An investigation card cites ten to twenty targets, and | ||
| * each request re-authorises and re-resolves the environment — so they go in one request. | ||
| */ | ||
|
|
||
| /** One environment lookup and one repo lookup serve a whole batch. */ | ||
| export const MAX_URIS_PER_RESOLVE_REQUEST = 25; | ||
|
|
||
| /** A transient failure is worth retrying; a third one isn't. */ | ||
| export const MAX_RESOLVE_ATTEMPTS = 3; | ||
|
|
||
| export const RESOLVE_RETRY_DELAY_MS = 1_000; | ||
|
|
||
| /** Deduplicates, then splits into requests no bigger than the cap. */ | ||
| export function planUriBatches( | ||
| uris: readonly string[], | ||
| cap: number = MAX_URIS_PER_RESOLVE_REQUEST | ||
| ): string[][] { | ||
| const unique = [...new Set(uris)]; | ||
| const batches: string[][] = []; | ||
| for (let index = 0; index < unique.length; index += cap) { | ||
| batches.push(unique.slice(index, index + cap)); | ||
| } | ||
| return batches; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔍 The
@deprecatednote is not true at this commit: AskAI is still mountedThe header says "Nothing mounts this any more — every Ask AI entry point now opens Ask Trigger."
AskAIRootis still rendered byapps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx:62and<AskAI />byapps/webapp/app/components/BlankStatePanels.tsx:295and:683.env.server.tslikewise now claimsKAPA_AI_WEBSITE_IDis unread "while no surface mounts the widget", butuseKapaWebsiteId()is still consumed by the mounted component. The notes are accurate only after the follow-up UI PR; as written they will mislead whoever does the promised removal of@kapaai/react-sdkand the env var.(Refers to lines 7-11)
Was this helpful? React with 👍 or 👎 to provide feedback.