Skip to content

feat(trigger-chat-agent): AI chat agent that teaches Trigger.dev by drawing - #126

Open
D-K-P wants to merge 37 commits into
mainfrom
add-trigger-chat-agent-example
Open

feat(trigger-chat-agent): AI chat agent that teaches Trigger.dev by drawing#126
D-K-P wants to merge 37 commits into
mainfrom
add-trigger-chat-agent-example

Conversation

@D-K-P

@D-K-P D-K-P commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

A new example: a Trigger.dev AI Chat agent that teaches you Trigger.dev by drawing instead of dumping paragraphs. Ask how a fan-out with retries works and you get an interactive React Flow node-graph; ask about retries and you get a short explainer, a quiz, and a gotcha callout. Every turn ends with clickable next-step chips so the learning keeps going.

How it's built

The agent is a single chat.agent() task, so the conversation is a durable run that survives redeploys and crashes with no database. It answers by calling a renderVisualization tool with a json-render spec built from a fixed component catalog (FlowGraph, Quiz, Callout, CodeCard, and more), which the Next.js frontend renders live with React Flow and shadcn/ui. The model supplies data, not markup, so every card is cheap and always well-formed.

Facts are grounded on the live docs through a documentation MCP server, and retrieved docs are quarantined as untrusted input before the model ever sees them. The system prompt is a versioned AI Prompt editable from the dashboard, and model calls emit standard GenAI telemetry spans, so you get token, cost and latency observability for free.

Also updates the root examples table with the new entry.

Summary by CodeRabbit

  • New Features
    • Added a Trigger.dev chat tutor with streaming conversations and suggested follow-up questions.
    • Added interactive React Flow diagrams, code cards, quizzes, statistics, prompts, glossaries, and step-by-step learning guides.
    • Added live documentation grounding, MCP integration, and secure handling of retrieved content.
    • Added responsive dark-themed styling, animations, reduced-motion support, and user-friendly error recovery.
  • Documentation
    • Added setup, configuration, example prompt, deployment, and environment variable guidance.

D-K-P added 30 commits August 6, 2026 11:08
Fork of clickhouse-chat-agent, reworked from data analytics to learning
Trigger.dev. Strips ClickHouse (client, listTables/describeTable/runQuery
tools, PointMap/maplibre) and the chart cards; swaps in an interactive
React Flow + dagre FlowGraph plus code/diagram/prompt/stat cards rendered
from json-render specs.

The chat.agent() keeps the versioned AI Prompt and renderVisualization
validate/retry loop, and merges a docs MCP server (default Context7,
DOCS_MCP_URL) into its tool set each turn to ground answers on the live
docs without inventing API surface.
Replace the parked shadcn-neutral styling with the Trigger.dev Launch Week
look: charcoal surfaces, apple-green accent, Satoshi titles. Adds the brand
palette as real CSS variables (so the React Flow SVG edge layer can read
them) and remaps the shadcn semantic tokens so the chat shell and the
json-render primitives inherit the look with no per-component overrides.
Satoshi loads from the Fontshare CDN via a <link> in the layout.
Turn the agent into a tutor, not just a diagram renderer. Adds a sandboxed
HTML `Lesson` catalog component (model-authored Tufte-style lesson with an
interactive quiz, rendered in an allow-scripts-only iframe so its JS can't
reach the app origin or session token) and a `suggestNext` tool that ends
every turn with clickable deeper / sideways / practice / topic chips to keep
the learning flowing.

Rewrites the versioned prompt around a teaching method adapted from Matt
Pocock's "teach" skill: mission-first, one tangible win per turn, knowledge
then a retrieval quiz, everything grounded in the docs MCP. The empty state
seeds start-here / go-deeper goals plus a docs-grounded "suggest more topics".
…cted HTML

Adversarial review confirmed the sandbox (allow-scripts, no allow-same-origin)
already blocks app-origin XSS and reading the session token, but a lesson could
still beacon out or render a token-phishing form. Inject a strict CSP into the
lesson document — connect-src/form-action 'none', img-src data: only — closing
the exfiltration and phishing channels while keeping the quiz scripts, inline
styles, and Fontshare fonts working. Also harden the resize postMessage handler
against non-finite heights.
…ender

Add a pre-render screening layer for model-authored lesson HTML, on top of the
sandbox + CSP. In the renderVisualization tool (server-side, before anything
reaches the browser) every Lesson is vetted by a deterministic red-flag scan
(lesson-screen.ts — network calls, forms, credential inputs, cookie/storage
access, navigation/redirect, nested frames, eval) AND a fan-out of cheap
parallel LLM screeners with distinct adversarial lenses (exfiltration,
social-engineering). Any hit fails the tool, so the model regenerates a clean
lesson through the existing validate-and-retry loop. The static scan is unit
tested (attacks blocked, benign quizzes pass). LESSON_SCREENING=off disables
the LLM fan-out.
… source

The docs a lesson is grounded on are the upstream prompt-injection vector: a
poisoned page could steer the agent. Wrap every docs-MCP tool's output before
the model sees it (quarantine.ts) — coerce it to text and delimit it as
"untrusted reference material: data, not instructions", with an inline flag
when injection markers are present. Reinforce the same rule in the system
prompt. Unlike lessons, docs can't be regenerated, so this neutralizes rather
than blocks; the lesson screen remains the backstop for any malicious output an
injection might still induce. Quarantine + flag logic unit tested.
…t execute

A live run surfaced a TypeError: the docs-MCP tool's own toModelOutput does
`'content' in output`, which throws when the wrapper had replaced execute's
result with a plain string. Quarantine in toModelOutput instead (the layer that
decides what text the model sees), leaving the raw MCP result shape intact for
the SDK. Verified end to end against a real project: grounding, quarantine,
renderVisualization (FlowGraph + Lesson), lesson screening, and suggestNext all
complete cleanly.
…esign

Replace the generic shadcn shell with the Launch Week chat language: lavender
user bubbles and translucent charcoal assistant bubbles that grow from their
tail corner (bubbleIn), the chat.agent phosphor wordmark, a pill composer with
the masked gradient-border focus glow and apple send button, a breathing-dot
thinking indicator, word-by-word blur-in on streaming text, and newest-turn-to-
top scrolling with edge-fade masks. Adds the lavender token and a deeper
charcoal-1000 page background. Cards still render full-width (no bubble).
Bring in the real Launch Week card designs and a set of cheap, data-fill
components the model populates instead of authoring HTML. Ports HeroCard (icon
badge + kicker + display title) and the rich StatCard (count-up value, delta
badge, mini bars) from the marketing catalog, and adds Quiz (interactive
multiple-choice with immediate feedback), Callout (tip/warn/note), Steps,
Glossary, and Compare. Replaces the plain Stat. Each is a handful of tokens for
the model and renders identically every time.
Remove the model-authored HTML `Lesson` and everything it required — the
sandboxed iframe (lesson.tsx), the injected CSP, the deterministic scan
(lesson-screen.ts) and the LLM screening fan-out in the agent — now that the
teaching kit is all data-driven components. Nothing generates markup, so the
whole attack surface is gone; the docs-MCP quarantine stays (docs are still
untrusted input). Rewrites the prompt to keep responses short and valuable
(components carry the density) and to steer the model across the new kit.
… often

Drop the per-word blur-in reveal (it read laggy) — assistant text now just
renders markdown as tokens stream in, the standard AI SDK approach, which feels
snappier. Steer the agent to frequently offer a "paste-ready prompt to scaffold
this in my repo" next-step chip and answer it with a PromptCard.
Persist conversations to Postgres, gated on DATABASE_URL — unset, the app runs
exactly as before with no sidebar; set, you get history, resume-on-reload and
delete. Showcases where the chat.agent lifecycle hooks belong: onChatStart
creates the row (once per chat), onTurnStart awaits the message write so the
question is durable before streaming AND sets the prompt (it fires on
continuation runs, where onChatStart doesn't), and onTurnComplete writes the
turn plus the resume cursor in one transaction so a refresh can't replay it.

Messages live in a single JSON column, so AI SDK upgrades need no migration.
Chats are owned by an anonymous cookie id minted in proxy.ts and every query is
scoped by it. Drizzle + pg against Supabase; pg avoids the prepared-statement
limitation of the transaction pooler.
Dagre was laying out every node as 128px wide — a constant carried over from a
design that assumed one-word labels — while the nodes actually rendered 150-300px.
Dagre reserved too little room, so siblings on a rank drew on top of each other.

Measure each node's width from its content and use that same value for both the
layout and the rendered node, so the two can't diverge; the serpentine grid gets
one column pitch sized to the widest node. Labels and sublabels are capped in the
catalog (22/24 chars) and truncate, and the schema now asks for at most ~10 nodes
and 3 branches per node so graphs stay readable in a chat column.
…architecture

Nothing was shown when a turn failed — the commonest case being `pnpm dev:trigger`
not running, which failed silently. Add an inline error banner with a retry (a
banner, not a toast: these are usually setup problems worth leaving on screen)
that maps failures to actionable text, including the dev-server case. Sanitise
errors server-side via uiMessageStreamOptions.onError so the browser gets a
useful message and the full error stays in the run log.

Also adds "Explain how this app is built" as a starting question, plus a factual
section in the prompt describing this app's architecture — the docs it grounds on
don't cover it, so without this the showcase question got a vague answer.
…duplicate prose

Restores auto-follow while an answer streams — I'd removed it when the entrance
felt jerky, but the blur was the culprit, not the scrolling. It's driven by a
ResizeObserver (message count doesn't change while text streams, so a
messages-keyed effect never fired) and disarms the moment the reader scrolls up,
re-arming at the bottom.

The composer now floats over the thread: content scrolls underneath and the last
inch masks into the background instead of stopping at a hard edge. Side rules on
the column so the overflowing Next chips read as clipped by a boundary, plus a
fade on that row.

Prompt: say each thing once (prose must not restate a card's contents) and call
suggestNext exactly once at the end of a turn — calling it repeatedly was
producing duplicated paragraphs and orphaned chip sets. Card text no longer
carries its own max-width: inside a card the card is the measure, so a 55ch cap
just left half the card empty.
Trigger.dev already persists the conversation: each chat.agent chat is backed by
a durable Session that outlives its runs, and the agent rebuilds full history
from a snapshot after an idle timeout, crash or redeploy. So the Postgres tables
were storing a second copy of what the platform already holds. Removes Drizzle,
pg and the schema/migrations, and rebuilds the sidebar on sessions.list().

Owner and title are stamped into session metadata when the session is created,
and the list is filtered by owner server-side so a browser only ever receives
its own chats. Two API limitations shaped this, both verified against 4.5.9:
sessions.update() returns Unauthorized even with a secret key, and
triggerConfig.tags is dropped at create time — so tags (which list can filter on
server-side) aren't usable, and metadata has to be set up front.

Opening an old chat resumes it and the agent remembers everything, but earlier
messages aren't redrawn: session.out is trimmed to ~one turn and there's no
public API to read the stored transcript. The UI says so rather than looking
broken. Verified live: turn runs, metadata persists, owner-scoped list returns
only that user's chat.
…er-side

Session tags go in the top-level `tags` field on session create, not
`triggerConfig.tags` (which tags each run the session schedules). That lets
sessions.list({ tag }) do the owner filtering server-side instead of listing
everything and narrowing in memory. Verified against 4.5.9: tags persist on the
session row and the tag filter returns just that owner's chats.
Back to a single-conversation demo: no sidebar, no chat list, no anonymous-user
cookie, no /chat/[id] route, no clientData. The example is one static page again
and needs nothing but a Trigger project and an Anthropic key.

The conversation is still durable — that's the platform's job, not the app's —
but nothing in the UI depends on enumerating or reopening past chats, which is
what all the removed machinery existed for.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b2d3ef25-03ea-4031-83af-52bba3da64b4

📥 Commits

Reviewing files that changed from the base of the PR and between 895a6e4 and 18a9027.

📒 Files selected for processing (2)
  • trigger-chat-agent/src/app/actions.ts
  • trigger-chat-agent/src/trigger/trigger-chat-agent.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • trigger-chat-agent/src/app/actions.ts
  • trigger-chat-agent/src/trigger/trigger-chat-agent.ts

Walkthrough

Adds a complete trigger-chat-agent Next.js example. The project includes Trigger.dev session actions, a streamed Anthropic chat agent, documentation MCP grounding with quarantine handling, validated JSON visualizations, and suggested-next tools. The client renders chat messages, documentation provenance, interactive graphs, diagrams, teaching cards, quizzes, code blocks, and markdown. It also adds project configuration, styling, setup documentation, and deployment instructions.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new Trigger.dev chat agent and its visual teaching approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-trigger-chat-agent-example

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (4)
trigger-chat-agent/trigger.config.ts (1)

4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fail fast when TRIGGER_PROJECT_REF is missing.

The non-null assertion hides a missing environment variable. The config then resolves project to undefined, and the CLI error does not point at the cause. Add an explicit check so the setup step in the README is enforced.

♻️ Proposed refactor
 import { defineConfig } from "`@trigger.dev/sdk`";
 
+const projectRef = process.env.TRIGGER_PROJECT_REF;
+if (!projectRef) {
+  throw new Error("TRIGGER_PROJECT_REF is not set. Copy .env.example to .env and set it.");
+}
+
 export default defineConfig({
-  project: process.env.TRIGGER_PROJECT_REF!,
+  project: projectRef,
   runtime: "node-22",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trigger-chat-agent/trigger.config.ts` at line 4, Replace the non-null
assertion on project in the Trigger configuration with an explicit validation of
TRIGGER_PROJECT_REF that fails immediately with a clear
missing-environment-variable error, ensuring setup cannot continue with an
undefined project value.
trigger-chat-agent/package.json (1)

5-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a lint script and ESLint dependencies, or remove the ESLint directive.

src/components/chat.tsx line 172 contains // eslint-disable-next-line react-hooks/exhaustive-deps, but this package declares no ESLint dependency and no lint script. Users who copy the example get no lint feedback.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trigger-chat-agent/package.json` around lines 5 - 11, Add a package-level
lint script and the required ESLint dependencies/configuration in package.json
so the existing directive in Chat component remains effective, or remove that
directive if linting is intentionally unsupported; ensure the chosen approach
gives copied examples consistent lint behavior.
trigger-chat-agent/src/components/chat.tsx (1)

610-619: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

This branch is unreachable; remove it or document why it stays.

groupMessageParts routes every part that is not text, tool-renderVisualization, or suggestNext into a docs group, and Message renders those groups with DocsToolChain. MessagePart therefore never receives a generic tool- or dynamic-tool part. The block duplicates the documentation-status presentation and will drift from DocsToolChain.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trigger-chat-agent/src/components/chat.tsx` around lines 610 - 619, The
generic tool/dynamic-tool branch in MessagePart is unreachable because
groupMessageParts routes those parts into the docs group. Remove the
startsWith("tool-")/dynamic-tool handling and rely on DocsToolChain for
documentation-status rendering, unless there is a demonstrated routing exception
that must be documented.
trigger-chat-agent/src/lib/quarantine.ts (1)

1-12: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the stale lesson-screen.ts reference.

No lesson-screen.ts file exists in the repository. Update the header comment so it does not reference removed code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trigger-chat-agent/src/lib/quarantine.ts` around lines 1 - 12, Update the
header comment in the quarantine module to remove the stale lesson-screen.ts
reference, while preserving the remaining description of the downstream
mitigation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@trigger-chat-agent/.gitignore`:
- Line 2: Update the ignore rules in .gitignore to cover all local environment
variants, including .env.local, .env.development.local, and
.env.production.local, while retaining the existing .env rule.

In `@trigger-chat-agent/src/app/actions.ts`:
- Around line 12-20: Update mintChatAccessToken to require an authenticated
caller and verify that the caller owns or may access the supplied chatId before
invoking auth.createPublicToken; reject unauthenticated or unauthorized
requests. If anonymous sessions are intentionally supported, document that
security requirement explicitly in the action instead of leaving the endpoint
unprotected.

In `@trigger-chat-agent/src/components/chat.tsx`:
- Around line 496-556: Update DocsToolChain to treat both output-available and
output-error states as terminal when computing complete, so failed lookups show
“Complete” and stop the searching animation. Preserve a distinct output-error
row indicator rather than rendering the successful Check icon for failed parts.

In `@trigger-chat-agent/src/components/error-notice.tsx`:
- Around line 53-58: Add role="alert" to the root div returned by the error
notice component so asynchronously rendered failures are announced to assistive
technology, leaving the existing styling and content unchanged.

In `@trigger-chat-agent/src/components/flow-graph.tsx`:
- Around line 450-472: Stabilize the nodes and sequence inputs used by the
status animation useEffect so replaceMessage’s deep-cloned but unchanged data
does not reset statuses or recreate timers. Derive content-based keys or
memoized array values from nodes and sequence, and use those stable dependencies
while preserving updates when their actual contents change.

In `@trigger-chat-agent/src/components/quiz.tsx`:
- Around line 36-62: Update the option buttons rendered in the options.map
callback to remain focusable after answered: replace the disabled attribute with
aria-disabled and guard the onClick handler so setPicked only runs before
answering. Mark the conditional explanation paragraph as an assertive live
region so its appearance is announced to assistive technologies.

In `@trigger-chat-agent/src/components/stat-card.tsx`:
- Around line 73-93: Update the onUpdate formatting in AnimatedValue so animated
numbers retain digit grouping when numText contains commas. Format the
interpolated value with grouping separators before combining it with prefix and
suffix, while preserving decimal precision and existing ungrouped-number
behavior.

In `@trigger-chat-agent/src/components/visualization.tsx`:
- Around line 11-40: Update VisualizationErrorBoundary usage in Visualization to
key the boundary by spec, ensuring repaired specifications mount a fresh
boundary and reset failed state. Add componentDidCatch to
VisualizationErrorBoundary to log rendering errors during development without
changing the existing fallback UI.

In `@trigger-chat-agent/src/lib/catalog.ts`:
- Around line 304-311: Update validateSpec to perform a reachability walk from
the root element using a visited set, following each element’s children and
rejecting any node encountered more than once as a cyclic or repeated reference.
Preserve the existing missing-child-key validation and return the accumulated
validation errors through the current result shape.

In `@trigger-chat-agent/src/trigger/trigger-chat-agent.ts`:
- Around line 48-67: Update loadDocsTools to initialize createMCPClient with
initializationOptions.timeout set to 10,000 ms, and replace client.tools() with
listTools({ options: { timeout: 10_000 } }) followed by
toolsFromDefinitions(...). Clear docsToolsPromise only when loading throws so
failed loads can retry, while preserving a valid empty tool set as a successful
cached result.

---

Nitpick comments:
In `@trigger-chat-agent/package.json`:
- Around line 5-11: Add a package-level lint script and the required ESLint
dependencies/configuration in package.json so the existing directive in Chat
component remains effective, or remove that directive if linting is
intentionally unsupported; ensure the chosen approach gives copied examples
consistent lint behavior.

In `@trigger-chat-agent/src/components/chat.tsx`:
- Around line 610-619: The generic tool/dynamic-tool branch in MessagePart is
unreachable because groupMessageParts routes those parts into the docs group.
Remove the startsWith("tool-")/dynamic-tool handling and rely on DocsToolChain
for documentation-status rendering, unless there is a demonstrated routing
exception that must be documented.

In `@trigger-chat-agent/src/lib/quarantine.ts`:
- Around line 1-12: Update the header comment in the quarantine module to remove
the stale lesson-screen.ts reference, while preserving the remaining description
of the downstream mitigation.

In `@trigger-chat-agent/trigger.config.ts`:
- Line 4: Replace the non-null assertion on project in the Trigger configuration
with an explicit validation of TRIGGER_PROJECT_REF that fails immediately with a
clear missing-environment-variable error, ensuring setup cannot continue with an
undefined project value.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a2df0c9a-246a-4da6-a147-033700484457

📥 Commits

Reviewing files that changed from the base of the PR and between a7f6fc1 and f31b070.

⛔ Files ignored due to path filters (2)
  • trigger-chat-agent/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • trigger-chat-agent/src/app/icon.svg is excluded by !**/*.svg
📒 Files selected for processing (34)
  • README.md
  • trigger-chat-agent/.env.example
  • trigger-chat-agent/.gitignore
  • trigger-chat-agent/README.md
  • trigger-chat-agent/components.json
  • trigger-chat-agent/next.config.ts
  • trigger-chat-agent/package.json
  • trigger-chat-agent/postcss.config.mjs
  • trigger-chat-agent/src/app/actions.ts
  • trigger-chat-agent/src/app/globals.css
  • trigger-chat-agent/src/app/layout.tsx
  • trigger-chat-agent/src/app/page.tsx
  • trigger-chat-agent/src/components/chat.tsx
  • trigger-chat-agent/src/components/code-card.tsx
  • trigger-chat-agent/src/components/diagram-card.tsx
  • trigger-chat-agent/src/components/error-notice.tsx
  • trigger-chat-agent/src/components/flow-graph.tsx
  • trigger-chat-agent/src/components/hero-card.tsx
  • trigger-chat-agent/src/components/prompt-card.tsx
  • trigger-chat-agent/src/components/quiz.tsx
  • trigger-chat-agent/src/components/stat-card.tsx
  • trigger-chat-agent/src/components/streaming-text.tsx
  • trigger-chat-agent/src/components/teaching-cards.tsx
  • trigger-chat-agent/src/components/visualization.tsx
  • trigger-chat-agent/src/components/wordmark.tsx
  • trigger-chat-agent/src/lib/catalog.ts
  • trigger-chat-agent/src/lib/code-theme.ts
  • trigger-chat-agent/src/lib/motion.ts
  • trigger-chat-agent/src/lib/quarantine.ts
  • trigger-chat-agent/src/lib/registry.tsx
  • trigger-chat-agent/src/lib/utils.ts
  • trigger-chat-agent/src/trigger/trigger-chat-agent.ts
  • trigger-chat-agent/trigger.config.ts
  • trigger-chat-agent/tsconfig.json

Comment thread trigger-chat-agent/.gitignore
Comment thread trigger-chat-agent/src/app/actions.ts
Comment thread trigger-chat-agent/src/components/chat.tsx
Comment thread trigger-chat-agent/src/components/error-notice.tsx
Comment thread trigger-chat-agent/src/components/flow-graph.tsx
Comment thread trigger-chat-agent/src/components/quiz.tsx Outdated
Comment thread trigger-chat-agent/src/components/stat-card.tsx
Comment thread trigger-chat-agent/src/components/visualization.tsx
Comment thread trigger-chat-agent/src/lib/catalog.ts
Comment thread trigger-chat-agent/src/trigger/trigger-chat-agent.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
trigger-chat-agent/src/lib/quarantine.ts (1)

63-65: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use the full UUID as the quarantine nonce.

crypto.randomUUID().slice(0, 8) keeps only 32 bits of entropy. The code uses this value as a second defense against forged reference fences. Keep the full UUID so future matcher changes do not reduce this defense to a guessable token.

Proposed fix
-  const nonce = crypto.randomUUID().slice(0, 8);
+  const nonce = crypto.randomUUID();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trigger-chat-agent/src/lib/quarantine.ts` around lines 63 - 65, Update the
nonce initialization in the quarantine fence construction to retain the full
value returned by crypto.randomUUID(), removing the .slice(0, 8) truncation
while preserving the existing per-call nonce behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@trigger-chat-agent/src/lib/quarantine.ts`:
- Around line 63-65: Update the nonce initialization in the quarantine fence
construction to retain the full value returned by crypto.randomUUID(), removing
the .slice(0, 8) truncation while preserving the existing per-call nonce
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ff5fdfc-34ae-4917-b3cc-87164a9e1f3f

📥 Commits

Reviewing files that changed from the base of the PR and between f31b070 and 895a6e4.

📒 Files selected for processing (12)
  • trigger-chat-agent/.gitignore
  • trigger-chat-agent/src/app/actions.ts
  • trigger-chat-agent/src/components/chat.tsx
  • trigger-chat-agent/src/components/error-notice.tsx
  • trigger-chat-agent/src/components/flow-graph.tsx
  • trigger-chat-agent/src/components/prompt-card.tsx
  • trigger-chat-agent/src/components/quiz.tsx
  • trigger-chat-agent/src/components/stat-card.tsx
  • trigger-chat-agent/src/components/visualization.tsx
  • trigger-chat-agent/src/lib/catalog.ts
  • trigger-chat-agent/src/lib/quarantine.ts
  • trigger-chat-agent/src/trigger/trigger-chat-agent.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • trigger-chat-agent/.gitignore
  • trigger-chat-agent/src/components/quiz.tsx
  • trigger-chat-agent/src/components/stat-card.tsx
  • trigger-chat-agent/src/app/actions.ts
  • trigger-chat-agent/src/components/visualization.tsx
  • trigger-chat-agent/src/components/error-notice.tsx
  • trigger-chat-agent/src/components/chat.tsx
  • trigger-chat-agent/src/lib/catalog.ts
  • trigger-chat-agent/src/components/flow-graph.tsx
  • trigger-chat-agent/src/trigger/trigger-chat-agent.ts
  • trigger-chat-agent/src/components/prompt-card.tsx

The session server actions are unauthenticated public POSTs, so a public
deployment can be driven to start unbounded agent runs. Cap parallel sessions
with a queue concurrencyLimit — this throttles throughput; pair it with an org
spend limit in the dashboard for the real ceiling. Also correct the actions.ts
security comment: chatId is an unguessable client id, so the practical risk is
cost/abuse, not session theft.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant