Skip to content

Restore custom Kapa chat with trigger-based support handoff - #466

Closed
dannyneira wants to merge 48 commits into
mainfrom
danny/kapa-custom-chat-handoff-v2
Closed

Restore custom Kapa chat with trigger-based support handoff#466
dannyneira wants to merge 48 commits into
mainfrom
danny/kapa-custom-chat-handoff-v2

Conversation

@dannyneira

Copy link
Copy Markdown
Member

Summary

  • restores the custom React-based Ask AI chat experience
  • adds trigger-based Create ticket handoff in the custom UI (conversation length >= 3, downvote, uncertainty)
  • stores and reuses Kapa thread IDs and builds a direct Kapa conversation link in the ticket draft
  • opens a prefilled mailto: handoff draft instead of relying on the prior server endpoint
  • re-enables required React/Kapa dependencies and adds PUBLIC_KAPA_PROJECT_ID env support

Validation

  • npm run typecheck
  • npm run build

Co-Authored-By: Warp Agent agent@warp.dev

dannyneira and others added 23 commits July 23, 2026 17:30
Adds an always-on Create ticket action in the Kapa chat UI, includes transcript context in submissions, and provides a preview/webhook backend endpoint for handoff testing.

Co-Authored-By: Oz <oz-agent@warp.dev>
Set the handoff endpoint to non-prerendered so static/SSR build inputs resolve correctly in CI and Vercel.

Co-Authored-By: Oz <oz-agent@warp.dev>
Move the custom handoff POST route to /kapa-handoff and remove the stale /api/kapa-handoff file to avoid CI/Vercel SSR rollup conflicts with the /api docs page.

Co-Authored-By: Oz <oz-agent@warp.dev>
Co-authored-by: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label Aug 4, 2026
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Aug 11, 2026 8:02pm

Request Review

Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
@dannyneira
dannyneira marked this pull request as ready for review August 8, 2026 00:09
@oz-for-oss

oz-for-oss Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

@dannyneira

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overview

This PR restores the custom Kapa chat UI, adds a support handoff flow, updates Kapa-related environment configuration, and expands CSP allowances for the chat dependencies.

Concerns

  • The new /api/support-handoff route is public and forwards ticket-creation payloads without server-side abuse protection.
  • The route falls back to a hard-coded external endpoint, so missing configuration can still send user email and chat transcript data to an implicit destination.

Security

  • Public support ticket forwarding needs server-side bot/rate-limit protection or a validated challenge token before it is exposed.
  • User support data should only be forwarded to an explicitly configured endpoint.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

return `https://app.kapa.ai/${kapaProjectId}/conversations/${kapaThreadId}`;
}

export const POST: APIRoute = async ({ request }) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] This public POST route forwards support-ticket payloads without bot protection, rate limiting, or a same-origin check, so anyone can script ticket creation with arbitrary email/transcript data. Require a server-validated Kapa/hCaptcha token or add rate limiting before forwarding.


export const POST: APIRoute = async ({ request }) => {
const supportHandoffEndpointUrl =
SUPPORT_HANDOFF_ENDPOINT_URL || DEFAULT_SUPPORT_HANDOFF_ENDPOINT_URL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Falling back to the hard-coded Hookdeck URL means any environment missing SUPPORT_HANDOFF_ENDPOINT_URL will still forward user email and chat transcripts to that endpoint. Fail closed when the env var is absent so PII only leaves via an explicitly configured destination.

Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
Root cause: astro-expressive-code's Vite plugin rewrites Shiki's bundled
theme registry (shiki/dist/themes.mjs) and strips every theme that is not
listed as a string in the Expressive Code `themes` config. Starlight
passes its themes as theme objects, so the registry was emptied to
`bundledThemesInfo = []` across the whole Vite module graph. The Kapa
side-chat island's runtime createHighlighter(['github-light',
'github-dark']) then threw "theme is not included in this bundle" and
every chat code block fell back to plaintext. The same stripping also
broke the earlier server-side /api/highlight-code approach.

Fix: set `removeUnusedThemes: false` in the Expressive Code config so
the registry ships intact. Theme data is still lazy-loaded, so only the
two requested GitHub themes are ever fetched in the browser, and docs
pages (build-time Expressive Code rendering) are unaffected.

Co-Authored-By: Warp Agent <agent@warp.dev>
Two flicker sources in the Kapa side-chat markdown rendering:

1. Inline code rendered as full code blocks. react-markdown v9+ no
   longer passes the `inline` flag to the `code` component, so the
   existing `if (inline)` branch never ran and every inline code span
   (e.g. `.rpm`, `zypper`) rendered as a framed ChatCodeBlock with a
   copy button and horizontal scrollbar. During streaming these frames
   popped in and out of the prose, causing large layout shifts. Fenced
   blocks are always emitted as <pre><code>, so block handling now
   lives in the `pre` component and bare `code` renders as a plain
   inline chip (already styled by KapaChatLauncher.css).

2. Per-token highlight churn. The `deferHighlight` prop (true while
   the answer is streaming) was accepted but never honored, so every
   streamed token queued a Shiki highlight of the partial code and the
   block flipped between plaintext and (stale) highlighted DOM. The
   highlight effect now skips work entirely while `deferHighlight` is
   set and highlights the final text once when streaming settles.
   Highlighted HTML is also keyed to the exact code text + theme it
   was produced for, so stale markup is never rendered.

Co-Authored-By: Warp Agent <agent@warp.dev>
Shiki's codeToHtml output separates each <span class="line"> with a
literal newline character, which the chat code block's
`white-space: pre` already renders as a line break. The extra
`.sl-kapa-codeblock code .line { display: block }` rule added a second
break per line, so every highlighted code block rendered with a blank
line between each line of code. Drop the rule and keep the line spans
inline.

Co-Authored-By: Warp Agent <agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant