@runtypelabs/persona 4.1.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.js +1 -1
- package/dist/index.cjs +53 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.global.js +41 -41
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +51 -51
- package/dist/index.js.map +1 -1
- package/dist/launcher.global.js +1 -1
- package/dist/launcher.global.js.map +1 -1
- package/dist/smart-dom-reader.d.cts +15 -0
- package/dist/smart-dom-reader.d.ts +15 -0
- package/dist/theme-editor-preview.cjs +46 -46
- package/dist/theme-editor-preview.d.cts +15 -0
- package/dist/theme-editor-preview.d.ts +15 -0
- package/dist/theme-editor-preview.js +46 -46
- package/dist/theme-editor.cjs +1 -1
- package/dist/theme-editor.d.cts +15 -0
- package/dist/theme-editor.d.ts +15 -0
- package/dist/theme-editor.js +1 -1
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.js +1 -1
- package/dist/widget.css +224 -0
- package/package.json +1 -1
- package/src/client.test.ts +128 -0
- package/src/client.ts +25 -0
- package/src/components/approval-actions.test.ts +309 -0
- package/src/components/approval-actions.ts +461 -0
- package/src/styles/widget.css +224 -0
- package/src/theme-reference.ts +2 -2
- package/src/types.ts +15 -0
- package/src/ui.ts +19 -3
- package/src/utils/tokens.ts +15 -12
package/dist/theme-reference.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var a in e)t(o,a,{get:e[a],enumerable:!0})},u=(o,e,a,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of d(e))!c.call(o,r)&&r!==a&&t(o,r,{get:()=>e[r],enumerable:!(s=l(e,r))||s.enumerable});return o};var g=o=>u(t({},"__esModule",{value:!0}),o);var h={};m(h,{THEME_EXAMPLES:()=>p,THEME_TOKEN_DOCS:()=>i,getThemeReference:()=>b});module.exports=g(h);var n={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var i={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides: semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals: backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color: buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500: Primary brand color.",secondary:"palette.colors.gray.500: Secondary color.",accent:"palette.colors.primary.600: Accent/interactive color.",surface:"palette.colors.gray.50: Panel/card backgrounds.",background:"palette.colors.gray.50: Page background.",container:"palette.colors.gray.100: Container backgrounds.",text:"palette.colors.gray.900: Primary text.",textMuted:"palette.colors.gray.500: Muted/secondary text.",textInverse:"palette.colors.gray.50: Text on dark backgrounds.",border:"palette.colors.gray.200: Default border color.",divider:"palette.colors.gray.200: Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight: reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text, shadow), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow: tool call row box-shadow.",reasoningBubble:"shadow: reasoning/thinking row box-shadow.",composer:"shadow: message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors: provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, reasonColor, reasonLabel, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[]: Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean: show/hide the header section entirely.",showFooter:"boolean: show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right": text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},p={darkIndigo:{description:"Dark mode with indigo accent: override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font: full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function b(){return{tokenDocs:i,defaultColorPalette:n.colors,defaultRadius:n.radius,examples:p,sdkPresets:["shop","minimal","fullscreen"]}}0&&(module.exports={THEME_EXAMPLES,THEME_TOKEN_DOCS,getThemeReference});
|
|
1
|
+
"use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var a in e)t(o,a,{get:e[a],enumerable:!0})},u=(o,e,a,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of d(e))!c.call(o,r)&&r!==a&&t(o,r,{get:()=>e[r],enumerable:!(s=l(e,r))||s.enumerable});return o};var g=o=>u(t({},"__esModule",{value:!0}),o);var h={};m(h,{THEME_EXAMPLES:()=>p,THEME_TOKEN_DOCS:()=>i,getThemeReference:()=>b});module.exports=g(h);var n={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var i={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides: semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals: backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color: buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500: Primary brand color.",secondary:"palette.colors.gray.500: Secondary color.",accent:"palette.colors.primary.600: Accent/interactive color.",surface:"palette.colors.gray.50: Panel/card backgrounds.",background:"palette.colors.gray.50: Page background.",container:"palette.colors.gray.100: Container backgrounds.",text:"palette.colors.gray.900: Primary text.",textMuted:"palette.colors.gray.500: Muted/secondary text.",textInverse:"palette.colors.gray.50: Text on dark backgrounds.",border:"palette.colors.gray.200: Default border color.",divider:"palette.colors.gray.200: Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight: reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text, shadow), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow: tool call row box-shadow.",reasoningBubble:"shadow: reasoning/thinking row box-shadow.",composer:"shadow: message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors: provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:`Tool approval card styling and behavior. Neutral surface card; the primary action anchors to the brand --persona-primary token. Set to false to disable. Set enableAlwaysAllow: true to add the split "Always allow / Allow once" control (needs a backend to persist the policy via onDecision's remember).`,properties:'enableAlwaysAllow, detailsDisplay ("collapsed" | "expanded" | "hidden"), showDetailsLabel, hideDetailsLabel, backgroundColor, borderColor, titleColor, descriptionColor, reasonColor, reasonLabel, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, approveLabel, denyLabel, formatDescription. (title no longer renders in the default card; use formatDescription to customize the summary.)'},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[]: Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean: show/hide the header section entirely.",showFooter:"boolean: show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right": text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},p={darkIndigo:{description:"Dark mode with indigo accent: override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font: full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function b(){return{tokenDocs:i,defaultColorPalette:n.colors,defaultRadius:n.radius,examples:p,sdkPresets:["shop","minimal","fullscreen"]}}0&&(module.exports={THEME_EXAMPLES,THEME_TOKEN_DOCS,getThemeReference});
|
package/dist/theme-reference.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var o={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides: semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals: backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color: buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500: Primary brand color.",secondary:"palette.colors.gray.500: Secondary color.",accent:"palette.colors.primary.600: Accent/interactive color.",surface:"palette.colors.gray.50: Panel/card backgrounds.",background:"palette.colors.gray.50: Page background.",container:"palette.colors.gray.100: Container backgrounds.",text:"palette.colors.gray.900: Primary text.",textMuted:"palette.colors.gray.500: Muted/secondary text.",textInverse:"palette.colors.gray.50: Text on dark backgrounds.",border:"palette.colors.gray.200: Default border color.",divider:"palette.colors.gray.200: Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight: reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text, shadow), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow: tool call row box-shadow.",reasoningBubble:"shadow: reasoning/thinking row box-shadow.",composer:"shadow: message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors: provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, reasonColor, reasonLabel, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[]: Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean: show/hide the header section entirely.",showFooter:"boolean: show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right": text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},r={darkIndigo:{description:"Dark mode with indigo accent: override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font: full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function m(){return{tokenDocs:o,defaultColorPalette:e.colors,defaultRadius:e.radius,examples:r,sdkPresets:["shop","minimal","fullscreen"]}}export{r as THEME_EXAMPLES,o as THEME_TOKEN_DOCS,m as getThemeReference};
|
|
1
|
+
var e={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var o={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides: semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals: backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color: buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500: Primary brand color.",secondary:"palette.colors.gray.500: Secondary color.",accent:"palette.colors.primary.600: Accent/interactive color.",surface:"palette.colors.gray.50: Panel/card backgrounds.",background:"palette.colors.gray.50: Page background.",container:"palette.colors.gray.100: Container backgrounds.",text:"palette.colors.gray.900: Primary text.",textMuted:"palette.colors.gray.500: Muted/secondary text.",textInverse:"palette.colors.gray.50: Text on dark backgrounds.",border:"palette.colors.gray.200: Default border color.",divider:"palette.colors.gray.200: Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight: reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text, shadow), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow: tool call row box-shadow.",reasoningBubble:"shadow: reasoning/thinking row box-shadow.",composer:"shadow: message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors: provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:`Tool approval card styling and behavior. Neutral surface card; the primary action anchors to the brand --persona-primary token. Set to false to disable. Set enableAlwaysAllow: true to add the split "Always allow / Allow once" control (needs a backend to persist the policy via onDecision's remember).`,properties:'enableAlwaysAllow, detailsDisplay ("collapsed" | "expanded" | "hidden"), showDetailsLabel, hideDetailsLabel, backgroundColor, borderColor, titleColor, descriptionColor, reasonColor, reasonLabel, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, approveLabel, denyLabel, formatDescription. (title no longer renders in the default card; use formatDescription to customize the summary.)'},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[]: Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean: show/hide the header section entirely.",showFooter:"boolean: show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right": text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},r={darkIndigo:{description:"Dark mode with indigo accent: override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font: full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function m(){return{tokenDocs:o,defaultColorPalette:e.colors,defaultRadius:e.radius,examples:r,sdkPresets:["shop","minimal","fullscreen"]}}export{r as THEME_EXAMPLES,o as THEME_TOKEN_DOCS,m as getThemeReference};
|
package/dist/widget.css
CHANGED
|
@@ -2405,6 +2405,230 @@
|
|
|
2405
2405
|
transform: scale(0.97);
|
|
2406
2406
|
}
|
|
2407
2407
|
|
|
2408
|
+
/* ============================================
|
|
2409
|
+
Approval card (default renderer, components/approval-actions.ts)
|
|
2410
|
+
Neutral surface card. Every color is a --persona-* token; the legacy
|
|
2411
|
+
--persona-approval-* shorthands are honored fallback-first so a consumer who
|
|
2412
|
+
themed them still wins, then the new semantic default applies.
|
|
2413
|
+
============================================ */
|
|
2414
|
+
.persona-approval-card {
|
|
2415
|
+
width: 100%;
|
|
2416
|
+
max-width: 100%;
|
|
2417
|
+
box-sizing: border-box;
|
|
2418
|
+
background: var(--persona-approval-bg, var(--persona-surface, #ffffff));
|
|
2419
|
+
border: 0.5px solid var(--persona-approval-border, var(--persona-border, rgba(11, 11, 11, 0.1)));
|
|
2420
|
+
border-radius: 0.75rem;
|
|
2421
|
+
padding: 0.5rem;
|
|
2422
|
+
}
|
|
2423
|
+
.persona-approval-card.persona-shadow-sm {
|
|
2424
|
+
box-shadow: var(--persona-approval-shadow, 0 1px 2px 0 rgba(11, 11, 11, 0.06), 0 2px 8px 0 rgba(11, 11, 11, 0.04));
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
.persona-approval-head {
|
|
2428
|
+
display: flex;
|
|
2429
|
+
align-items: center;
|
|
2430
|
+
gap: 0.75rem;
|
|
2431
|
+
width: 100%;
|
|
2432
|
+
border: none;
|
|
2433
|
+
background: transparent;
|
|
2434
|
+
padding: 0.4rem 0.6rem;
|
|
2435
|
+
cursor: pointer;
|
|
2436
|
+
text-align: left;
|
|
2437
|
+
font: inherit;
|
|
2438
|
+
color: var(--persona-text, #0b0b0b);
|
|
2439
|
+
border-radius: 0.5rem;
|
|
2440
|
+
transition: background 0.12s ease;
|
|
2441
|
+
}
|
|
2442
|
+
.persona-approval-head:hover { background: var(--persona-container, rgba(11, 11, 11, 0.04)); }
|
|
2443
|
+
.persona-approval-head[data-static="true"] { cursor: default; }
|
|
2444
|
+
.persona-approval-head[data-static="true"]:hover { background: transparent; }
|
|
2445
|
+
|
|
2446
|
+
.persona-approval-logo {
|
|
2447
|
+
flex-shrink: 0;
|
|
2448
|
+
width: 24px;
|
|
2449
|
+
height: 24px;
|
|
2450
|
+
display: grid;
|
|
2451
|
+
place-items: center;
|
|
2452
|
+
box-sizing: border-box;
|
|
2453
|
+
border: 0.5px solid var(--persona-border, rgba(11, 11, 11, 0.12));
|
|
2454
|
+
border-radius: 6.5px;
|
|
2455
|
+
background: var(--persona-surface, #ffffff);
|
|
2456
|
+
box-shadow: 0 1px 2px 0 rgba(11, 11, 11, 0.08);
|
|
2457
|
+
color: var(--persona-muted, #6b7280);
|
|
2458
|
+
overflow: hidden;
|
|
2459
|
+
}
|
|
2460
|
+
.persona-approval-logo svg { width: 15px; height: 15px; display: block; }
|
|
2461
|
+
|
|
2462
|
+
.persona-approval-title {
|
|
2463
|
+
flex: 1;
|
|
2464
|
+
min-width: 0;
|
|
2465
|
+
font-size: 0.875rem;
|
|
2466
|
+
line-height: 1.4;
|
|
2467
|
+
color: var(--persona-text, #0b0b0b);
|
|
2468
|
+
}
|
|
2469
|
+
.persona-approval-title strong { font-weight: 600; }
|
|
2470
|
+
|
|
2471
|
+
.persona-approval-toggle {
|
|
2472
|
+
display: inline-flex;
|
|
2473
|
+
align-items: center;
|
|
2474
|
+
margin-left: 0.25rem;
|
|
2475
|
+
color: var(--persona-muted, #6b7280);
|
|
2476
|
+
vertical-align: middle;
|
|
2477
|
+
transition: transform 0.15s ease;
|
|
2478
|
+
}
|
|
2479
|
+
.persona-approval-toggle svg { width: 0.85rem; height: 0.85rem; display: block; }
|
|
2480
|
+
.persona-approval-head[aria-expanded="false"] .persona-approval-toggle { transform: rotate(-90deg); }
|
|
2481
|
+
|
|
2482
|
+
.persona-approval-body {
|
|
2483
|
+
padding: 0.5rem 0.6rem 0.35rem calc(24px + 0.75rem + 0.6rem);
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
.persona-approval-details {
|
|
2487
|
+
margin: 0 0 0.75rem;
|
|
2488
|
+
}
|
|
2489
|
+
.persona-approval-details[hidden] { display: none; }
|
|
2490
|
+
|
|
2491
|
+
.persona-approval-desc {
|
|
2492
|
+
margin: 0 0 0.5rem;
|
|
2493
|
+
font-size: 0.8125rem;
|
|
2494
|
+
line-height: 1.4;
|
|
2495
|
+
color: var(--persona-muted, #6b7280);
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
.persona-approval-params {
|
|
2499
|
+
margin: 0;
|
|
2500
|
+
padding: 0.7rem 0.85rem;
|
|
2501
|
+
border-radius: 0.625rem;
|
|
2502
|
+
background: var(--persona-container, rgba(11, 11, 11, 0.04));
|
|
2503
|
+
color: var(--persona-text, #1f2937);
|
|
2504
|
+
font-size: 0.75rem;
|
|
2505
|
+
line-height: 1rem;
|
|
2506
|
+
overflow-x: auto;
|
|
2507
|
+
max-height: 9rem;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
.persona-approval-reason {
|
|
2511
|
+
margin: 0 0 0.6rem;
|
|
2512
|
+
font-size: 0.8125rem;
|
|
2513
|
+
line-height: 1.4;
|
|
2514
|
+
color: var(--persona-muted, #6b7280);
|
|
2515
|
+
}
|
|
2516
|
+
.persona-approval-reason-label { font-weight: 500; }
|
|
2517
|
+
|
|
2518
|
+
.persona-approval-resolved {
|
|
2519
|
+
display: flex;
|
|
2520
|
+
align-items: center;
|
|
2521
|
+
gap: 0.45rem;
|
|
2522
|
+
margin: 0.5rem 0;
|
|
2523
|
+
padding: 0.3rem 0.15rem;
|
|
2524
|
+
font-size: 0.8rem;
|
|
2525
|
+
color: var(--persona-muted, #6b7280);
|
|
2526
|
+
}
|
|
2527
|
+
.persona-approval-resolved svg { width: 0.95rem; height: 0.95rem; display: block; flex-shrink: 0; }
|
|
2528
|
+
.persona-approval-resolved-name { font-weight: 600; }
|
|
2529
|
+
|
|
2530
|
+
.persona-approval-actions {
|
|
2531
|
+
display: flex;
|
|
2532
|
+
align-items: center;
|
|
2533
|
+
gap: 0.5rem;
|
|
2534
|
+
flex-wrap: wrap;
|
|
2535
|
+
}
|
|
2536
|
+
.persona-approval-split { position: relative; display: inline-flex; }
|
|
2537
|
+
|
|
2538
|
+
.persona-approval-primary,
|
|
2539
|
+
.persona-approval-caret,
|
|
2540
|
+
.persona-approval-deny {
|
|
2541
|
+
border: none;
|
|
2542
|
+
cursor: pointer;
|
|
2543
|
+
font: inherit;
|
|
2544
|
+
font-size: 0.875rem;
|
|
2545
|
+
font-weight: 500;
|
|
2546
|
+
height: 2rem;
|
|
2547
|
+
display: inline-flex;
|
|
2548
|
+
align-items: center;
|
|
2549
|
+
gap: 0.375rem;
|
|
2550
|
+
transition: background 0.12s ease, box-shadow 0.12s ease;
|
|
2551
|
+
}
|
|
2552
|
+
/* Primary anchors to the brand token via the established button-primary pair. */
|
|
2553
|
+
.persona-approval-primary {
|
|
2554
|
+
background: var(--persona-approval-approve-bg, var(--persona-button-primary-bg, var(--persona-primary, #111827)));
|
|
2555
|
+
color: var(--persona-button-primary-fg, var(--persona-text-inverse, #ffffff));
|
|
2556
|
+
padding: 0 0.75rem;
|
|
2557
|
+
border-radius: 0.5rem 0 0 0.5rem;
|
|
2558
|
+
}
|
|
2559
|
+
.persona-approval-primary--solo { border-radius: 0.5rem; }
|
|
2560
|
+
.persona-approval-caret {
|
|
2561
|
+
position: relative;
|
|
2562
|
+
background: var(--persona-approval-approve-bg, var(--persona-button-primary-bg, var(--persona-primary, #111827)));
|
|
2563
|
+
color: var(--persona-button-primary-fg, var(--persona-text-inverse, #ffffff));
|
|
2564
|
+
width: 2rem;
|
|
2565
|
+
justify-content: center;
|
|
2566
|
+
padding: 0;
|
|
2567
|
+
border-radius: 0 0.5rem 0.5rem 0;
|
|
2568
|
+
}
|
|
2569
|
+
.persona-approval-caret svg { width: 0.95rem; height: 0.95rem; display: block; }
|
|
2570
|
+
.persona-approval-caret::before {
|
|
2571
|
+
content: "";
|
|
2572
|
+
position: absolute;
|
|
2573
|
+
left: 0;
|
|
2574
|
+
top: 4px;
|
|
2575
|
+
bottom: 4px;
|
|
2576
|
+
width: 1px;
|
|
2577
|
+
background: var(--persona-button-primary-fg, #ffffff);
|
|
2578
|
+
opacity: 0.25;
|
|
2579
|
+
transition: opacity 0.12s ease;
|
|
2580
|
+
}
|
|
2581
|
+
.persona-approval-caret:hover::before,
|
|
2582
|
+
.persona-approval-primary:hover + .persona-approval-caret::before { opacity: 0; }
|
|
2583
|
+
.persona-approval-primary:hover,
|
|
2584
|
+
.persona-approval-caret:hover { box-shadow: inset 0 0 0 999px rgba(255, 255, 255, 0.16); }
|
|
2585
|
+
|
|
2586
|
+
.persona-approval-deny {
|
|
2587
|
+
background: var(--persona-approval-deny-bg, var(--persona-container, rgba(11, 11, 11, 0.04)));
|
|
2588
|
+
color: var(--persona-text, #1f2937);
|
|
2589
|
+
padding: 0 0.75rem;
|
|
2590
|
+
border-radius: 0.5rem;
|
|
2591
|
+
box-shadow: inset 0 0 0 0.5px var(--persona-border, rgba(0, 0, 0, 0.1));
|
|
2592
|
+
}
|
|
2593
|
+
.persona-approval-deny:hover { box-shadow: inset 0 0 0 0.5px var(--persona-border, rgba(0, 0, 0, 0.1)), inset 0 0 0 999px rgba(11, 11, 11, 0.04); }
|
|
2594
|
+
|
|
2595
|
+
.persona-approval-menu {
|
|
2596
|
+
width: max-content;
|
|
2597
|
+
max-width: 18rem;
|
|
2598
|
+
box-sizing: border-box;
|
|
2599
|
+
background: var(--persona-surface, #ffffff);
|
|
2600
|
+
border: 0.5px solid var(--persona-border, rgba(11, 11, 11, 0.1));
|
|
2601
|
+
border-radius: 0.625rem;
|
|
2602
|
+
box-shadow: 0 8px 24px rgba(11, 11, 11, 0.12), 0 2px 6px rgba(11, 11, 11, 0.08);
|
|
2603
|
+
padding: 0.25rem;
|
|
2604
|
+
white-space: nowrap;
|
|
2605
|
+
}
|
|
2606
|
+
.persona-approval-menu-item {
|
|
2607
|
+
display: flex;
|
|
2608
|
+
align-items: center;
|
|
2609
|
+
gap: 0.6rem;
|
|
2610
|
+
width: 100%;
|
|
2611
|
+
border: none;
|
|
2612
|
+
background: transparent;
|
|
2613
|
+
cursor: pointer;
|
|
2614
|
+
font: inherit;
|
|
2615
|
+
font-size: 0.875rem;
|
|
2616
|
+
color: var(--persona-text, #1f2937);
|
|
2617
|
+
padding: 0.45rem 0.6rem;
|
|
2618
|
+
border-radius: 0.4rem;
|
|
2619
|
+
text-align: left;
|
|
2620
|
+
transition: background 0.12s ease;
|
|
2621
|
+
}
|
|
2622
|
+
.persona-approval-menu-item:hover { background: var(--persona-container, rgba(11, 11, 11, 0.06)); }
|
|
2623
|
+
.persona-approval-kbd {
|
|
2624
|
+
font-family: inherit;
|
|
2625
|
+
font-size: 0.75rem;
|
|
2626
|
+
line-height: 1;
|
|
2627
|
+
opacity: 0.7;
|
|
2628
|
+
margin-left: 0.25rem;
|
|
2629
|
+
}
|
|
2630
|
+
.persona-approval-menu-item .persona-approval-kbd { margin-left: auto; }
|
|
2631
|
+
|
|
2408
2632
|
/* ============================================
|
|
2409
2633
|
Visibility (Tailwind parity: prefix persona-)
|
|
2410
2634
|
Shipped widget.css is hand-maintained; these utilities are used in TS but not generated by Tailwind at build time.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runtypelabs/persona",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
package/src/client.test.ts
CHANGED
|
@@ -1784,6 +1784,134 @@ describe('AgentWidgetClient - partId Text/Tool Interleaving', () => {
|
|
|
1784
1784
|
});
|
|
1785
1785
|
});
|
|
1786
1786
|
|
|
1787
|
+
describe('AgentWidgetClient - flow continuation stream without execution_start', () => {
|
|
1788
|
+
// A tool-driven `/resume` continues a flow on a brand-new stream that does NOT
|
|
1789
|
+
// re-emit `execution_start` (`flow_start`). Each stream resolves its execution
|
|
1790
|
+
// kind independently and defaults to `"agent"`, so the continuation used to
|
|
1791
|
+
// mis-route the final prompt-step finalization: the streamed text block was
|
|
1792
|
+
// sealed via the agent path (which never records it as the sealed flow bubble),
|
|
1793
|
+
// then `step_complete.result.response` re-rendered the same text as a SECOND
|
|
1794
|
+
// bubble. The client now recovers the flow kind from the leading `step_*`
|
|
1795
|
+
// frame (a `stepType` is flow-only), so the finalization reconciles in place.
|
|
1796
|
+
function collectAssistantTexts(events: AgentWidgetEvent[]) {
|
|
1797
|
+
const messagesById = new Map<string, AgentWidgetMessage>();
|
|
1798
|
+
for (const event of events) {
|
|
1799
|
+
if (event.type === 'message') messagesById.set(event.message.id, event.message);
|
|
1800
|
+
}
|
|
1801
|
+
return Array.from(messagesById.values())
|
|
1802
|
+
.filter(m => m.role === 'assistant' && !m.variant)
|
|
1803
|
+
.sort((a, b) => (a.sequence ?? 0) - (b.sequence ?? 0));
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
it('does not duplicate the final message when a flow resumes without execution_start', async () => {
|
|
1807
|
+
const events: AgentWidgetEvent[] = [];
|
|
1808
|
+
|
|
1809
|
+
// No `flow_start`/`execution_start`: this is exactly the wire a tool-driven
|
|
1810
|
+
// `/resume` continuation delivers.
|
|
1811
|
+
global.fetch = createAgentStreamFetch([
|
|
1812
|
+
sseEvent('step_start', { id: 's1', name: 'Prompt', stepType: 'prompt', index: 0, totalSteps: 1 }),
|
|
1813
|
+
sseEvent('text_start', { messageId: 'msg_s1' }),
|
|
1814
|
+
sseEvent('step_delta', { id: 's1', text: 'Done! Added to your cart.' }),
|
|
1815
|
+
sseEvent('text_end', { messageId: 'msg_s1' }),
|
|
1816
|
+
// The authoritative final response mirrors the streamed text.
|
|
1817
|
+
sseEvent('step_complete', { id: 's1', name: 'Prompt', stepType: 'prompt', success: true, result: { response: 'Done! Added to your cart.' }, executionTime: 500 }),
|
|
1818
|
+
sseEvent('flow_complete', { success: true }),
|
|
1819
|
+
]);
|
|
1820
|
+
|
|
1821
|
+
const client = new AgentWidgetClient({ apiUrl: 'http://localhost:8000' });
|
|
1822
|
+
await client.dispatch(
|
|
1823
|
+
{ messages: [{ id: 'usr_1', role: 'user', content: 'add it to my cart', createdAt: new Date().toISOString() }] },
|
|
1824
|
+
(event) => events.push(event)
|
|
1825
|
+
);
|
|
1826
|
+
|
|
1827
|
+
const assistantTexts = collectAssistantTexts(events);
|
|
1828
|
+
|
|
1829
|
+
// Exactly ONE assistant bubble — not duplicated by the step_complete finalization.
|
|
1830
|
+
expect(assistantTexts.length).toBe(1);
|
|
1831
|
+
expect(assistantTexts[0].content).toBe('Done! Added to your cart.');
|
|
1832
|
+
expect(assistantTexts[0].streaming).toBe(false);
|
|
1833
|
+
});
|
|
1834
|
+
|
|
1835
|
+
it('still reconciles in place when execution_start IS present (initial flow stream)', async () => {
|
|
1836
|
+
const events: AgentWidgetEvent[] = [];
|
|
1837
|
+
|
|
1838
|
+
// Same shape but WITH flow_start — the pre-existing, already-correct path.
|
|
1839
|
+
global.fetch = createAgentStreamFetch([
|
|
1840
|
+
sseEvent('flow_start', { flowId: 'f1', flowName: 'Test', totalSteps: 1, executionId: 'exec_f1' }),
|
|
1841
|
+
sseEvent('step_start', { id: 's1', name: 'Prompt', stepType: 'prompt', index: 0, totalSteps: 1 }),
|
|
1842
|
+
sseEvent('text_start', { messageId: 'msg_s1' }),
|
|
1843
|
+
sseEvent('step_delta', { id: 's1', text: 'Done! Added to your cart.' }),
|
|
1844
|
+
sseEvent('text_end', { messageId: 'msg_s1' }),
|
|
1845
|
+
sseEvent('step_complete', { id: 's1', name: 'Prompt', stepType: 'prompt', success: true, result: { response: 'Done! Added to your cart.' }, executionTime: 500 }),
|
|
1846
|
+
sseEvent('flow_complete', { success: true }),
|
|
1847
|
+
]);
|
|
1848
|
+
|
|
1849
|
+
const client = new AgentWidgetClient({ apiUrl: 'http://localhost:8000' });
|
|
1850
|
+
await client.dispatch(
|
|
1851
|
+
{ messages: [{ id: 'usr_1', role: 'user', content: 'add it to my cart', createdAt: new Date().toISOString() }] },
|
|
1852
|
+
(event) => events.push(event)
|
|
1853
|
+
);
|
|
1854
|
+
|
|
1855
|
+
const assistantTexts = collectAssistantTexts(events);
|
|
1856
|
+
expect(assistantTexts.length).toBe(1);
|
|
1857
|
+
expect(assistantTexts[0].content).toBe('Done! Added to your cart.');
|
|
1858
|
+
expect(assistantTexts[0].streaming).toBe(false);
|
|
1859
|
+
});
|
|
1860
|
+
|
|
1861
|
+
it('does not misclassify an agent stream as a flow (no stepType present)', async () => {
|
|
1862
|
+
const events: AgentWidgetEvent[] = [];
|
|
1863
|
+
const execId = 'exec_a1';
|
|
1864
|
+
|
|
1865
|
+
// Agent loops use `agent_*`/turn_* frames and never carry a `stepType`, so the
|
|
1866
|
+
// flow recovery must not engage. A single streamed turn yields exactly one
|
|
1867
|
+
// bubble (regression guard so the recovery can't over-fire on agents).
|
|
1868
|
+
global.fetch = createAgentStreamFetch([
|
|
1869
|
+
sseEvent('agent_start', {
|
|
1870
|
+
executionId: execId, agentId: 'virtual', agentName: 'Test',
|
|
1871
|
+
maxTurns: 1, startedAt: new Date().toISOString(), seq: 1,
|
|
1872
|
+
}),
|
|
1873
|
+
sseEvent('agent_iteration_start', {
|
|
1874
|
+
executionId: execId, iteration: 1, maxTurns: 1,
|
|
1875
|
+
startedAt: new Date().toISOString(), seq: 2,
|
|
1876
|
+
}),
|
|
1877
|
+
sseEvent('agent_turn_start', {
|
|
1878
|
+
executionId: execId, iteration: 1, turnIndex: 0,
|
|
1879
|
+
role: 'assistant', turnId: 'turn_1', seq: 3,
|
|
1880
|
+
}),
|
|
1881
|
+
sseEvent('agent_turn_delta', {
|
|
1882
|
+
executionId: execId, iteration: 1, delta: 'Hi there!',
|
|
1883
|
+
contentType: 'text', turnId: 'turn_1', seq: 4,
|
|
1884
|
+
}),
|
|
1885
|
+
sseEvent('agent_turn_complete', {
|
|
1886
|
+
executionId: execId, iteration: 1, role: 'assistant',
|
|
1887
|
+
turnId: 'turn_1', completedAt: new Date().toISOString(), seq: 5,
|
|
1888
|
+
}),
|
|
1889
|
+
sseEvent('agent_iteration_complete', {
|
|
1890
|
+
executionId: execId, iteration: 1, toolCallsMade: 0,
|
|
1891
|
+
stopConditionMet: false, completedAt: new Date().toISOString(), seq: 6,
|
|
1892
|
+
}),
|
|
1893
|
+
sseEvent('agent_complete', {
|
|
1894
|
+
executionId: execId, agentId: 'virtual', success: true,
|
|
1895
|
+
iterations: 1, stopReason: 'max_iterations',
|
|
1896
|
+
completedAt: new Date().toISOString(), seq: 7,
|
|
1897
|
+
}),
|
|
1898
|
+
]);
|
|
1899
|
+
|
|
1900
|
+
const client = new AgentWidgetClient({
|
|
1901
|
+
apiUrl: 'http://localhost:8000',
|
|
1902
|
+
agent: { name: 'Test', model: 'openai:gpt-4o-mini', systemPrompt: 'test' },
|
|
1903
|
+
});
|
|
1904
|
+
await client.dispatch(
|
|
1905
|
+
{ messages: [{ id: 'usr_1', role: 'user', content: 'hi', createdAt: new Date().toISOString() }] },
|
|
1906
|
+
(event) => events.push(event)
|
|
1907
|
+
);
|
|
1908
|
+
|
|
1909
|
+
const assistantTexts = collectAssistantTexts(events);
|
|
1910
|
+
expect(assistantTexts.length).toBe(1);
|
|
1911
|
+
expect(assistantTexts[0].content).toBe('Hi there!');
|
|
1912
|
+
});
|
|
1913
|
+
});
|
|
1914
|
+
|
|
1787
1915
|
describe('AgentWidgetClient - nested flow-as-tool (parentToolCallId)', () => {
|
|
1788
1916
|
// PR #4602: a flow running as a tool enriches its streamed text/reasoning with
|
|
1789
1917
|
// toolContext.toolId; the unified wire surfaces it as text_start/reasoning_start
|
package/src/client.ts
CHANGED
|
@@ -1969,6 +1969,15 @@ export class AgentWidgetClient {
|
|
|
1969
1969
|
// Execution kind, resolved from the leading `execution_start` frame. Drives
|
|
1970
1970
|
// the agent-vs-flow branches that the single unified vocabulary collapses.
|
|
1971
1971
|
let executionKind: "agent" | "flow" = "agent";
|
|
1972
|
+
// Whether `executionKind` was set authoritatively by an `execution_start`
|
|
1973
|
+
// frame. Continuation streams (e.g. a tool-driven `/resume`) do NOT re-emit
|
|
1974
|
+
// `execution_start`, so a fresh `streamResponse` for the continuation starts
|
|
1975
|
+
// with the default `"agent"`. For a flow that mis-routes the final
|
|
1976
|
+
// prompt-step finalization and duplicates the last message (the streamed
|
|
1977
|
+
// text block is sealed, then `step_complete.result.response` re-renders it as
|
|
1978
|
+
// a second bubble). When `execution_start` is absent we recover the flow kind
|
|
1979
|
+
// from the first flow `step_*` frame below.
|
|
1980
|
+
let executionKindResolved = false;
|
|
1972
1981
|
// Open turn id (from `turn_start`). Unified text/reasoning deltas carry their
|
|
1973
1982
|
// own block id, not the turn id, so the turn id is threaded onto agentMetadata
|
|
1974
1983
|
// from here.
|
|
@@ -1987,6 +1996,21 @@ export class AgentWidgetClient {
|
|
|
1987
1996
|
const payloadType = seqReadyQueue[i].payloadType;
|
|
1988
1997
|
const payload = seqReadyQueue[i].payload;
|
|
1989
1998
|
|
|
1999
|
+
// Recover the execution kind on continuation streams that omit
|
|
2000
|
+
// `execution_start` (e.g. a tool-driven `/resume`). Flow `step_*` frames
|
|
2001
|
+
// carry a `stepType`; agent loops never do (they use `turn_*`). Without
|
|
2002
|
+
// this, the continuation defaults to `"agent"` and a flow's final
|
|
2003
|
+
// prompt-step finalization is duplicated. We only infer when no
|
|
2004
|
+
// `execution_start` resolved the kind, so an explicit `agent` is never
|
|
2005
|
+
// overridden.
|
|
2006
|
+
if (
|
|
2007
|
+
!executionKindResolved &&
|
|
2008
|
+
executionKind !== "flow" &&
|
|
2009
|
+
typeof (payload as { stepType?: unknown }).stepType === "string"
|
|
2010
|
+
) {
|
|
2011
|
+
executionKind = "flow";
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1990
2014
|
if (payloadType === "reasoning_start") {
|
|
1991
2015
|
// Nested flow-as-tool thinking (PR #4602): route to the parent tool's row.
|
|
1992
2016
|
const rStartBlockId = typeof payload.id === "string" ? payload.id : null;
|
|
@@ -2543,6 +2567,7 @@ export class AgentWidgetClient {
|
|
|
2543
2567
|
// ================================================================
|
|
2544
2568
|
} else if (payloadType === "execution_start") {
|
|
2545
2569
|
executionKind = payload.kind === "flow" ? "flow" : "agent";
|
|
2570
|
+
executionKindResolved = true;
|
|
2546
2571
|
if (executionKind === "agent") {
|
|
2547
2572
|
agentExecution = {
|
|
2548
2573
|
executionId: payload.executionId,
|