feat(chat): support custom local chats in portal (long system prompt + flat render)#6
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… export type Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the BroadcastChannel-based system-prompt transmission with a
generic one-shot "set then get": the host stores an AgentInitConfig
({ prompt, title }, extensible) in sessionStorage under a per-instance
crypto.randomUUID() key and passes that key to the iframe via the
initConfig query param. The iframe reads its own key from the URL and
applies the config once on mount.
This is same-origin only, not reactive, and isolates several chats in
the same tab (each instance has a distinct key). Drops useSystemPromptChannel,
the AgentSetSystemPrompt message type, the fixed df-agent-system-prompt
storage key, and the title URL param (title now lives in the config).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a third agent-chat variant alongside menu and drawer: a block that renders the chat iframe flat in the page (the caller wraps it in a card). Being always visible, it has no toggle, open/close state, unread badge, or auto-open — but it reuses createAgentChatBase so it still participates in the ready/ping/pong discovery handshake (action buttons can target it) and handles navigate messages. - make storageKey optional in createAgentChatBase (a flat block has no open/closed state to persist); menu/drawer keep passing their keys - add useAgentChatBlock singleton composable (isOpen = ref(true), no key) - add DfAgentChatBlock.vue filling its container (height/width 100%) - export the component, composable and AgentChatBlockState type - add _dev/chat-block demo page and e2e spec Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The per-chat initConfig refactor appended `?initConfig=<key>` to the chat
iframe URL, which broke the `url().endsWith('/_dev/chat')` frame matcher in the
drawer, menu and action specs (chat-system-prompt already used the fix). Match
on `new URL(url).pathname` instead, as those specs now do.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndom UUIDs
setAgentInitConfig writes to sessionStorage under a per-key entry that is never
removed, so a fresh crypto.randomUUID() per mount leaked a new entry on every
page visit within a tab. Default each variant to a stable key ('menu', 'drawer',
'block') so re-mounts overwrite in place and storage stays bounded to one entry
per variant. A page can host one of each variant without clobbering; mounting
several of the same variant is the only case that needs the new optional
initConfigKey prop to force a distinct key.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d plan Remove the superseded BroadcastChannel plan/spec and update architecture docs to reflect the shipped approach: the DfAgentChatBlock flat render and the sessionStorage init-config handoff for systemPrompt/title. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Add the capabilities needed to embed custom local chats in a portal: an arbitrarily long system prompt and a flat (inline) chat render.
What changed:
systemPromptandtitleare handed to the chat iframe through same-origin sessionStorage init-config (lib-vue/agent-init-config.ts, keyed by a?initConfig=<key>URL param) instead of URL query params.resolveAgentChatUrlnow only appends?initConfig=<key>;AgentChat.vuereads the config on mount, taking precedence over props.DfAgentChatBlock+useAgentChatBlock: the chat iframe rendered inline in a page, always visible, no FAB/drawer/popover.createAgentChatBase'sstorageKeyis now optional since a block has no open/close state to persist._dev/chat-block,_dev/chat-drawer) and e2e specs for the block, system-prompt transmission, and the legacy?systemPrompt=path. Existing chat e2e helpers now match the iframe by pathname to tolerate the newinitConfigquery param.docs/embedding-guide.md(new Block component, init-config section, corrected URL-resolution section) anddocs/architecture.md(block variant + init-config channel).Why: the iframe URL passes through nginx (~8KB request-line limit → HTTP 414); after percent-encoding, a URL-borne system prompt safely tops out around ~2KB, too small for real custom-agent prompts, and it leaked into nginx logs / history /
Referer. sessionStorage removes both the size limit and the exposure. The block variant lets a portal embed the chat inline rather than only as a floating overlay.Regression risks:
resolveAgentChatUrlno longer carriestitle/systemPromptin the URL from the drawer/menu/block components. The legacy direct-URL path (chat.vuereading those query params) is unchanged and still works (covered by a dedicated e2e test). Risk only if an embedder mounts these components against an iframe target that reads URL params exclusively, or uses a customsrcthat ignores init-config.createAgentChatBase(isOpen, storageKey?)signature change —storageKeyis now optional with guardedlocalStoragewrites. Existing drawer/menu callers pass it unchanged; only the new block omits it.drawer/menu/block) mean two instances of the same variant in one tab would clobber each other's config; overridable via theinitConfigKeyprop.