@frankieai/react 0.2.20 → 0.2.21

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/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ ActionConfirm: () => ActionConfirm,
24
25
  Avatar: () => Avatar,
25
26
  Badge: () => Badge,
26
27
  Button: () => Button,
@@ -124,6 +125,8 @@ var FrankieClient = class {
124
125
  session;
125
126
  /** Identity (JWT `sub`, else the raw token) the cached session was issued for. */
126
127
  sessionUserKey;
128
+ /** The host token fetched for the latest turn; sent with it so tools get a live one. */
129
+ latestUserToken;
127
130
  get sessionId() {
128
131
  return this.session?.sessionId;
129
132
  }
@@ -185,6 +188,7 @@ var FrankieClient = class {
185
188
  "user_token_unavailable"
186
189
  );
187
190
  }
191
+ this.latestUserToken = userToken;
188
192
  const userKey = sessionIdentity(userToken);
189
193
  if (userKey !== this.sessionUserKey) this.resetSession();
190
194
  if (this.session && new Date(this.session.expiresAt).getTime() > Date.now() + 3e4) return this.session;
@@ -277,7 +281,11 @@ var FrankieClient = class {
277
281
  message: input.message,
278
282
  ...input.context ? { context: input.context } : {},
279
283
  ...input.model ? { model: input.model } : {},
280
- ...input.attachments?.length ? { attachments: input.attachments } : {}
284
+ ...input.attachments?.length ? { attachments: input.attachments } : {},
285
+ ...this.latestUserToken ? { userToken: this.latestUserToken } : {},
286
+ // This widget shows the approval card, so the server may pause writes for it.
287
+ confirmActions: true,
288
+ ...input.confirm ? { confirm: input.confirm } : {}
281
289
  };
282
290
  const response = await this.doFetch(`${this.baseUrl}/v1/chat`, {
283
291
  method: "POST",
@@ -312,7 +320,7 @@ var FrankieClient = class {
312
320
  await this.postToolResult(session, callId, result).catch(() => void 0);
313
321
  }
314
322
  async callHostApi(request) {
315
- const api = this.options.api;
323
+ const api = this.options.api ?? (typeof window !== "undefined" ? { baseUrl: window.location.origin } : void 0);
316
324
  if (!api) {
317
325
  return {
318
326
  status: 0,
@@ -419,6 +427,10 @@ function luminance([r, g, b]) {
419
427
  };
420
428
  return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
421
429
  }
430
+ function colorful([r, g, b]) {
431
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
432
+ return max - min >= 40;
433
+ }
422
434
  function contrastRatio(a, b) {
423
435
  const la = luminance(a), lb = luminance(b);
424
436
  return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
@@ -527,7 +539,7 @@ function inferHostTheme() {
527
539
  break;
528
540
  }
529
541
  const text = parseRgb(style.color);
530
- if (text && text[3] > 0.5 && !sameColor(text, foreground)) {
542
+ if (text && text[3] > 0.5 && !sameColor(text, foreground) && colorful(text)) {
531
543
  accent = text;
532
544
  break;
533
545
  }
@@ -605,6 +617,11 @@ function applyEvent(message, event) {
605
617
  } : tool
606
618
  )
607
619
  };
620
+ case "action_confirm":
621
+ return {
622
+ ...message,
623
+ action: { toolUseId: event.toolUseId, name: event.name, label: event.label, preview: event.preview, state: "pending" }
624
+ };
608
625
  case "tool_denied":
609
626
  return {
610
627
  ...message,
@@ -824,6 +841,7 @@ function useFrankieChatState() {
824
841
  ...context ? { context } : {},
825
842
  ...opts?.model ? { model: opts.model } : {},
826
843
  ...attachments.length ? { attachments } : {},
844
+ ...opts?.confirm ? { confirm: opts.confirm } : {},
827
845
  signal: abort.signal
828
846
  },
829
847
  (event) => {
@@ -894,6 +912,21 @@ function useFrankieChatState() {
894
912
  },
895
913
  [busy, client, context, patchAssistant, restored, followRunningTurn]
896
914
  );
915
+ const answerAction = (0, import_react.useCallback)(
916
+ async (toolUseId, approved) => {
917
+ if (abortRef.current) return;
918
+ const holder = messagesRef.current.find(
919
+ (message) => message.role === "assistant" && message.action?.toolUseId === toolUseId && message.action.state === "pending"
920
+ );
921
+ if (!holder) return;
922
+ patchAssistant(
923
+ holder.id,
924
+ (message) => message.action ? { ...message, action: { ...message.action, state: approved ? "approved" : "cancelled" } } : message
925
+ );
926
+ await send(approved ? "Go ahead" : "Cancel", { confirm: { toolUseId, approved } });
927
+ },
928
+ [patchAssistant, send]
929
+ );
897
930
  const stop = (0, import_react.useCallback)(() => {
898
931
  if (!abortRef.current) return;
899
932
  void client.stopTurn();
@@ -914,7 +947,7 @@ function useFrankieChatState() {
914
947
  } catch {
915
948
  }
916
949
  }, [client]);
917
- return { messages, busy, loadedSkills, activeApis, restoring: !restored, ...error ? { error } : {}, send, stop, reset };
950
+ return { messages, busy, loadedSkills, activeApis, restoring: !restored, ...error ? { error } : {}, send, answerAction, stop, reset };
918
951
  }
919
952
  function conversationTitle(messages) {
920
953
  const first = messages.find((message) => message.role === "user" && message.text.trim());
@@ -1028,7 +1061,7 @@ function useFrankieTheme() {
1028
1061
  }
1029
1062
 
1030
1063
  // src/components/chat/FrankieWidget.tsx
1031
- var import_lucide_react8 = require("lucide-react");
1064
+ var import_lucide_react9 = require("lucide-react");
1032
1065
  var import_react11 = require("react");
1033
1066
 
1034
1067
  // src/lib/styles-ready.ts
@@ -1036,7 +1069,7 @@ var import_react3 = require("react");
1036
1069
 
1037
1070
  // src/generated/css-content.ts
1038
1071
  var FRANKIE_CSS_CONTENT = `/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
1039
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-ease:initial}}}@layer theme{.frankie-root{--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--color-background:var(--frankie-background);--color-foreground:var(--frankie-foreground);--color-primary:var(--frankie-primary)}}@layer components{.frankie-page-shell{background:var(--frankie-background);height:100%;min-height:0;color:var(--frankie-foreground);flex:1;display:flex}.frankie-page-main{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.frankie-history-desktop{border-right:1px solid var(--frankie-border);background:var(--frankie-secondary);flex-direction:column;flex-shrink:0;gap:16px;width:260px;padding:20px 14px;transition:width .16s,padding .16s;display:flex;overflow:auto}.frankie-history-toggle{border:1px solid var(--frankie-border);background:var(--frankie-background);width:32px;height:32px;color:var(--frankie-muted-foreground);cursor:pointer;border-radius:8px;flex-shrink:0;justify-content:center;align-self:flex-end;align-items:center;display:flex}.frankie-history-toggle:hover{color:var(--frankie-foreground)}.frankie-history-collapsed{width:56px;padding:20px 8px;overflow:visible}.frankie-history-collapsed .frankie-history-toggle{align-self:center}.frankie-history-heading{justify-content:space-between;align-items:center;font-size:14px;display:flex}.frankie-new-chat{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;gap:8px;min-height:44px;font-weight:600;display:flex}.frankie-history-search>span{color:var(--frankie-muted-foreground);margin-bottom:6px;font-size:12px;display:block}.frankie-history-search input{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:8px;width:100%;min-height:40px;padding:8px 10px}.frankie-history-list{flex-direction:column;flex:1;gap:4px;display:flex}.frankie-history-list button{text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:8px;flex-direction:column;align-items:flex-start;gap:5px;min-height:54px;padding:10px;display:flex}.frankie-history-list button span{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:13px;overflow:hidden}.frankie-history-list small{color:var(--frankie-muted-foreground);font-size:11px}.frankie-history-list button:hover,.frankie-history-list button[aria-current]{background:var(--frankie-background);border-color:var(--frankie-border)}.frankie-history-desktop>p,.frankie-history-dialog p{color:var(--frankie-muted-foreground);font-size:13px}.frankie-header-caption{color:var(--frankie-muted-foreground);font-size:12px}.frankie-page-header button{cursor:pointer;justify-content:center;align-items:center;gap:6px;min-width:40px;min-height:40px;display:inline-flex}.frankie-chat-settings{position:relative}.frankie-chat-settings summary{cursor:pointer;border-radius:8px;place-items:center;width:40px;height:40px;list-style:none;display:grid}.frankie-chat-settings summary::-webkit-details-marker{display:none}.frankie-chat-settings>div{z-index:5;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:12px;gap:12px;width:min(280px,80vw);padding:16px;font-size:13px;display:grid;position:absolute;top:46px;right:0;box-shadow:0 10px 30px #0002}.frankie-chat-settings p{color:var(--frankie-muted-foreground);margin:0}.frankie-loaded-skills{width:100%;max-width:760px;color:var(--frankie-muted-foreground);font-size:12px}.frankie-loaded-skills summary{cursor:pointer;padding:6px 0}.frankie-loaded-skills ul{margin:0;padding:4px 0;list-style:none}.frankie-loaded-skills li{gap:8px;padding:4px 0;display:flex}.frankie-loaded-skills small{opacity:.7}.frankie-history-dialog{background:var(--frankie-secondary);width:min(320px,86vw);max-width:none;height:100dvh;max-height:none;color:var(--frankie-foreground);border:0;margin:0;padding:0}.frankie-history-dialog::backdrop{background:#0008}.frankie-history-dialog>aside{height:100%;padding:calc(20px + env(safe-area-inset-top)) 16px calc(20px + env(safe-area-inset-bottom));flex-direction:column;gap:16px;display:flex;overflow:auto}.frankie-mobile-only{display:none!important}.frankie-widget-panel{max-height:calc(100dvh - 100px - var(--frankie-lift,0px))}.frankie-root button:focus-visible,.frankie-root summary:focus-visible,.frankie-root input:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:3px}.frankie-root button:disabled{opacity:.5;cursor:not-allowed}@media (max-width:760px){.frankie-history-desktop{display:none}.frankie-mobile-only{display:inline-flex!important}.frankie-header-caption{display:none}.frankie-page-header{padding:6px 10px}.frankie-history-heading button{background:0 0;border:0;justify-content:center;align-items:center;min-width:44px;min-height:44px}.frankie-page-prompts{gap:8px}.frankie-widget-panel{width:calc(100vw - 32px)}}.frankie-root{--frankie-styles-ready:1;--frankie-background:#fff;--frankie-foreground:#0a0a0a;--frankie-primary:#171717;--frankie-primary-foreground:#fafafa;--frankie-secondary:#f5f5f5;--frankie-secondary-foreground:#171717;--frankie-muted:#f5f5f5;--frankie-muted-foreground:#737373;--frankie-border:#e5e5e5;--frankie-radius:.625rem;--frankie-font:ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;font-family:var(--frankie-font);color:var(--frankie-foreground);-webkit-font-smoothing:antialiased;line-height:1.5}.frankie-root.dark{--frankie-background:#0a0a0a;--frankie-foreground:#fafafa;--frankie-primary:#fafafa;--frankie-primary-foreground:#171717;--frankie-secondary:#262626;--frankie-secondary-foreground:#fafafa;--frankie-muted:#262626;--frankie-muted-foreground:#a3a3a3;--frankie-border:#262626}.frankie-root,.frankie-root *,.frankie-root :before,.frankie-root :after{box-sizing:border-box}.frankie-root button,.frankie-root textarea,.frankie-root input{font:inherit;color:inherit;margin:0}.frankie-root button{background-color:#0000;border:0 solid}.frankie-root textarea{background-color:var(--frankie-background)}.frankie-focus:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:2px}.frankie-scroll{scrollbar-width:thin;scrollbar-color:var(--frankie-border) transparent}.frankie-prose>*+*{margin-top:.6rem}.frankie-prose p{white-space:pre-wrap;overflow-wrap:anywhere;margin:0;line-height:1.6}.frankie-prose>.frankie-h{letter-spacing:-.01em;margin-top:1.15rem;line-height:1.3}.frankie-prose>.frankie-h:first-child{margin-top:0}.frankie-prose h3.frankie-h{font-size:1.06em;font-weight:700}.frankie-prose h4.frankie-h{font-size:1em;font-weight:600}.frankie-prose h5.frankie-h{color:var(--frankie-muted-foreground);font-size:.92em;font-weight:600}.frankie-prose strong{font-weight:600}.frankie-prose ul,.frankie-prose ol{flex-direction:column;gap:.35rem;margin:0;padding-left:1.4rem;display:flex}.frankie-prose li{padding-left:.15rem;line-height:1.55}.frankie-prose li::marker{color:var(--frankie-muted-foreground)}.frankie-prose ul{list-style:outside}.frankie-prose ol{list-style:decimal}.frankie-prose a{color:var(--frankie-primary);text-underline-offset:2px;text-decoration:underline}.frankie-prose code{background-color:var(--frankie-muted);border-radius:.25rem;padding:.1em .3em;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.85em}.frankie-prose pre{border-radius:var(--frankie-radius);background-color:var(--frankie-muted);margin:0;padding:.625rem .75rem;overflow-x:auto}.frankie-prose pre code{background:0 0;padding:0}.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, var(--frankie-primary), transparent 65%), var(--frankie-background);flex-direction:column;min-width:0;display:flex;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, color-mix(in srgb, var(--frankie-primary) 8%, transparent), transparent 65%), var(--frankie-background)}}.frankie-chat-page{color:var(--frankie-foreground)}.frankie-page-header{border-bottom:1px solid var(--frankie-border);background:var(--frankie-background);flex:0 0 56px;justify-content:space-between;align-items:center;gap:16px;min-height:56px;padding:0 24px;display:flex}@supports (color:color-mix(in lab, red, red)){.frankie-page-header{background:color-mix(in srgb, var(--frankie-background) 92%, transparent)}}.frankie-page-header{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.frankie-page-header>div{align-items:center;gap:10px;display:flex}.frankie-page-header strong{font-size:.925rem;font-weight:650}.frankie-page-status{background:var(--frankie-primary);width:10px;height:10px;box-shadow:0 0 0 4px var(--frankie-primary);border-radius:999px}@supports (color:color-mix(in lab, red, red)){.frankie-page-status{box-shadow:0 0 0 4px color-mix(in srgb, var(--frankie-primary) 16%, transparent)}}.frankie-page-header button{border:1px solid var(--frankie-border);border-radius:calc(var(--frankie-radius) * .9);background:var(--frankie-secondary);cursor:pointer;min-height:36px;padding:0 13px}.frankie-page-header button:hover{border-color:var(--frankie-primary)}.frankie-page-canvas{flex:1;min-width:0;min-height:0;display:flex}.frankie-page-canvas>.frankie-inline{width:100%;max-width:56rem;margin:0 auto}.frankie-page-canvas .frankie-scroll{padding:2rem clamp(1rem,4vw,4rem) 1.25rem}.frankie-page-canvas .frankie-root>.border-t{background:linear-gradient(180deg, transparent, var(--frankie-background) 30%);border-top:0;padding:.75rem clamp(1rem,4vw,4rem) 1.5rem}.frankie-page-empty{text-align:center;flex-direction:column;flex-shrink:0;justify-content:safe center;align-items:center;gap:2rem;width:min(100%,44rem);min-height:100%;margin:auto;padding:clamp(2rem,7vh,4.5rem) 1rem 2rem;display:flex;container-type:inline-size}.frankie-page-welcome h1{letter-spacing:-.02em;margin:0;font-size:clamp(1.55rem,3.4vw,2rem);font-weight:700;line-height:1.15}.frankie-page-welcome p{max-width:34rem;color:var(--frankie-muted-foreground);margin:.6rem auto 0;font-size:1rem}.frankie-page-suggest{flex-direction:column;align-items:center;gap:1rem;width:100%;display:flex}.frankie-page-suggest-label{color:var(--frankie-muted-foreground);letter-spacing:.12em;text-transform:uppercase;margin:0;font-size:.72rem;font-weight:600}.frankie-page-prompts{grid-template-columns:1fr;gap:.75rem;width:100%;display:grid}@container (min-width:30rem){.frankie-page-prompts{grid-template-columns:repeat(2,minmax(0,1fr))}}.frankie-page-prompts button{border:1px solid var(--frankie-border);background:var(--frankie-background);text-align:left;cursor:pointer;border-radius:14px;align-items:flex-start;gap:.85rem;min-height:64px;padding:.9rem 1rem;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-page-prompts button:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-page-prompts button:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 4%, var(--frankie-background))}}.frankie-page-prompts button:hover:not(:disabled){transform:translateY(-1px)}.frankie-prompt-icon{background:var(--frankie-muted);width:34px;height:34px;color:var(--frankie-foreground);border-radius:9px;flex:none;place-items:center;display:grid}.frankie-prompt-text{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-prompt-text strong{font-size:.9rem;font-weight:600;line-height:1.3}.frankie-prompt-text small{color:var(--frankie-muted-foreground);font-size:.8rem;line-height:1.35;overflow:hidden}.frankie-page-suggest-hint{color:var(--frankie-muted-foreground);margin:0;font-size:.85rem}.frankie-widget-panel .frankie-page-empty{gap:1rem;padding:1rem .25rem}.frankie-widget-panel .frankie-page-welcome h1{font-size:1.25rem}.frankie-widget-panel .frankie-page-welcome p{margin-top:.35rem;font-size:.88rem;line-height:1.45}.frankie-widget-panel .frankie-page-suggest{gap:.55rem}.frankie-widget-panel .frankie-page-suggest-label{font-size:.66rem}.frankie-widget-panel .frankie-page-prompts{flex-wrap:wrap;justify-content:center;gap:.4rem;display:flex}.frankie-widget-panel .frankie-page-prompts button{border-radius:999px;align-items:center;gap:.4rem;max-width:100%;min-height:34px;padding:.3rem .8rem .3rem .45rem}.frankie-widget-panel .frankie-prompt-icon{border-radius:999px;width:22px;height:22px}.frankie-widget-panel .frankie-prompt-icon svg{width:13px;height:13px}.frankie-widget-panel .frankie-prompt-text strong{white-space:nowrap;text-overflow:ellipsis;font-size:.82rem;font-weight:550;overflow:hidden}.frankie-widget-panel .frankie-prompt-text small,.frankie-widget-panel .frankie-page-suggest-hint{display:none}@media (max-width:640px){.frankie-page-header{flex-basis:52px;min-height:52px;padding:0 12px}.frankie-page-canvas .frankie-scroll{padding:1.25rem .75rem .5rem}.frankie-page-canvas .frankie-root>.border-t{padding:.65rem .75rem calc(.65rem + env(safe-area-inset-bottom))}}}@layer utilities;.frankie-root .\\@container{container-type:inline-size}.frankie-root .invisible{visibility:hidden}.frankie-root .visible{visibility:visible}.frankie-root .absolute{position:absolute}.frankie-root .fixed{position:fixed}.frankie-root .relative{position:relative}.frankie-root .static{position:static}.frankie-root .sticky{position:sticky}.frankie-root .isolate{isolation:isolate}.frankie-root .container{width:100%}@media (min-width:40rem){.frankie-root .container{max-width:40rem}}@media (min-width:48rem){.frankie-root .container{max-width:48rem}}@media (min-width:64rem){.frankie-root .container{max-width:64rem}}@media (min-width:80rem){.frankie-root .container{max-width:80rem}}@media (min-width:96rem){.frankie-root .container{max-width:96rem}}.frankie-root .mt-0{margin-top:0}.frankie-root .mt-0\\.5{margin-top:calc(var(--spacing) * .5)}.frankie-root .mt-1{margin-top:var(--spacing)}.frankie-root .mt-2{margin-top:calc(var(--spacing) * 2)}.frankie-root .block{display:block}.frankie-root .contents{display:contents}.frankie-root .flex{display:flex}.frankie-root .grid{display:grid}.frankie-root .hidden{display:none}.frankie-root .inline{display:inline}.frankie-root .inline-flex{display:inline-flex}.frankie-root .table{display:table}.frankie-root .size-1{width:var(--spacing);height:var(--spacing)}.frankie-root .size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.frankie-root .size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.frankie-root .size-3\\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.frankie-root .size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.frankie-root .size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.frankie-root .size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.frankie-root .size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.frankie-root .size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.frankie-root .size-full{width:100%;height:100%}.frankie-root .h-8{height:calc(var(--spacing) * 8)}.frankie-root .h-9{height:calc(var(--spacing) * 9)}.frankie-root .h-10{height:calc(var(--spacing) * 10)}.frankie-root .h-\\[32rem\\]{height:32rem}.frankie-root .h-full{height:100%}.frankie-root .h-px{height:1px}.frankie-root .min-h-7{min-height:calc(var(--spacing) * 7)}.frankie-root .min-h-\\[2\\.25rem\\]{min-height:2.25rem}.frankie-root .min-h-screen{min-height:100vh}.frankie-root .w-\\[22rem\\]{width:22rem}.frankie-root .w-full{width:100%}.frankie-root .max-w-\\[12rem\\]{max-width:12rem}.frankie-root .max-w-\\[14rem\\]{max-width:14rem}.frankie-root .max-w-\\[85\\%\\]{max-width:85%}.frankie-root .max-w-\\[calc\\(100vw-2rem\\)\\]{max-width:calc(100vw - 2rem)}.frankie-root .min-w-0{min-width:0}.frankie-root .flex-1{flex:1}.frankie-root .shrink-0{flex-shrink:0}.frankie-root .grow{flex-grow:1}.frankie-root .animate-pulse{animation:var(--animate-pulse)}.frankie-root .animate-spin{animation:var(--animate-spin)}.frankie-root .cursor-pointer{cursor:pointer}.frankie-root .resize{resize:both}.frankie-root .resize-none{resize:none}.frankie-root .list-none{list-style-type:none}.frankie-root .flex-col{flex-direction:column}.frankie-root .flex-wrap{flex-wrap:wrap}.frankie-root .items-center{align-items:center}.frankie-root .items-end{align-items:flex-end}.frankie-root .items-start{align-items:flex-start}.frankie-root .justify-center{justify-content:center}.frankie-root .justify-end{justify-content:flex-end}.frankie-root .gap-1{gap:var(--spacing)}.frankie-root .gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.frankie-root .gap-2{gap:calc(var(--spacing) * 2)}.frankie-root .gap-3{gap:calc(var(--spacing) * 3)}.frankie-root .gap-4{gap:calc(var(--spacing) * 4)}.frankie-root .truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.frankie-root .overflow-hidden{overflow:hidden}.frankie-root .overflow-y-auto{overflow-y:auto}.frankie-root .overscroll-contain{overscroll-behavior:contain}.frankie-root .rounded{border-radius:.25rem}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)\\+4px\\)\\]{border-radius:calc(var(--frankie-radius) + 4px)}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)-2px\\)\\]{border-radius:calc(var(--frankie-radius) - 2px)}.frankie-root .rounded-\\[var\\(--frankie-radius\\)\\]{border-radius:var(--frankie-radius)}.frankie-root .rounded-full{border-radius:3.40282e38px}.frankie-root .rounded-md{border-radius:var(--radius-md)}.frankie-root .rounded-none{border-radius:0}.frankie-root .border{border-style:var(--tw-border-style);border-width:1px}.frankie-root .border-0{border-style:var(--tw-border-style);border-width:0}.frankie-root .border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.frankie-root .border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.frankie-root .border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.frankie-root .border-border{border-color:var(--frankie-border)}.frankie-root .border-transparent{border-color:#0000}.frankie-root .bg-background{background-color:var(--frankie-background)}.frankie-root .bg-border{background-color:var(--frankie-border)}.frankie-root .bg-emerald-500{background-color:var(--color-emerald-500)}.frankie-root .bg-emerald-500\\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-emerald-500\\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.frankie-root .bg-muted{background-color:var(--frankie-muted)}.frankie-root .bg-muted-foreground{background-color:var(--frankie-muted-foreground)}.frankie-root .bg-primary{background-color:var(--frankie-primary)}.frankie-root .bg-red-500{background-color:var(--color-red-500)}.frankie-root .bg-red-500\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-red-500\\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.frankie-root .bg-secondary{background-color:var(--frankie-secondary)}.frankie-root .object-cover{object-fit:cover}.frankie-root .p-3{padding:calc(var(--spacing) * 3)}.frankie-root .p-4{padding:calc(var(--spacing) * 4)}.frankie-root .px-1{padding-inline:var(--spacing)}.frankie-root .px-2{padding-inline:calc(var(--spacing) * 2)}.frankie-root .px-3{padding-inline:calc(var(--spacing) * 3)}.frankie-root .px-4{padding-inline:calc(var(--spacing) * 4)}.frankie-root .px-6{padding-inline:calc(var(--spacing) * 6)}.frankie-root .py-0{padding-block:0}.frankie-root .py-0\\.5{padding-block:calc(var(--spacing) * .5)}.frankie-root .py-1{padding-block:var(--spacing)}.frankie-root .py-2{padding-block:calc(var(--spacing) * 2)}.frankie-root .py-3{padding-block:calc(var(--spacing) * 3)}.frankie-root .pl-2{padding-left:calc(var(--spacing) * 2)}.frankie-root .text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.frankie-root .text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.frankie-root .text-\\[0\\.625rem\\]{font-size:.625rem}.frankie-root .text-\\[0\\.6875rem\\]{font-size:.6875rem}.frankie-root .text-\\[11px\\]{font-size:11px}.frankie-root .leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.frankie-root .font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.frankie-root .font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.frankie-root .whitespace-nowrap{white-space:nowrap}.frankie-root .text-emerald-600{color:var(--color-emerald-600)}.frankie-root .text-foreground{color:var(--frankie-foreground)}.frankie-root .text-muted-foreground{color:var(--frankie-muted-foreground)}.frankie-root .text-primary{color:var(--frankie-primary)}.frankie-root .text-primary-foreground{color:var(--frankie-primary-foreground)}.frankie-root .text-red-600{color:var(--color-red-600)}.frankie-root .text-secondary-foreground{color:var(--frankie-secondary-foreground)}.frankie-root .italic{font-style:italic}.frankie-root .underline-offset-4{text-underline-offset:4px}.frankie-root .opacity-60{opacity:.6}.frankie-root .opacity-70{opacity:.7}.frankie-root .shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .outline{outline-style:var(--tw-outline-style);outline-width:1px}.frankie-root .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.frankie-root .select-all{-webkit-user-select:all;user-select:all}.frankie-root .placeholder\\:text-muted-foreground::placeholder{color:var(--frankie-muted-foreground)}@media (hover:hover){.frankie-root .hover\\:border-border:hover{border-color:var(--frankie-border)}.frankie-root .hover\\:bg-muted:hover{background-color:var(--frankie-muted)}.frankie-root .hover\\:text-foreground:hover{color:var(--frankie-foreground)}.frankie-root .hover\\:underline:hover{text-decoration-line:underline}.frankie-root .hover\\:opacity-90:hover{opacity:.9}.frankie-root .hover\\:opacity-100:hover{opacity:1}}.frankie-root .focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .focus-visible\\:ring-primary:focus-visible{--tw-ring-color:var(--frankie-primary)}.frankie-root .focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.frankie-root .disabled\\:pointer-events-none:disabled{pointer-events:none}.frankie-root .disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.frankie-root .disabled\\:opacity-50:disabled{opacity:.5}.frankie-root .dark\\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.frankie-root .dark\\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.frankie-root .\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.frankie-root .\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.frankie-root .\\[\\&\\:\\:-webkit-details-marker\\]\\:hidden::-webkit-details-marker{display:none}.frankie-root.frankie-chat-panel{min-height:0;position:relative}.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px var(--frankie-primary), 0 12px 28px -12px #0f172a47, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px color-mix(in srgb, var(--frankie-primary) 22%, #0f172a6b), 0 12px 28px -12px #0f172a47, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 8%, transparent)}}.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 12%, transparent)}}.frankie-root .frankie-agent-context-wrap{flex:none;justify-content:center;padding:12px 10px;display:flex}.frankie-root .frankie-agent-context{max-width:100%;color:var(--frankie-foreground);font-size:13px;position:relative}.frankie-root .frankie-agent-context>summary{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:10px;min-height:44px;padding:7px 13px;list-style:none;display:flex;box-shadow:0 1px 3px #0000000d}.frankie-root .frankie-agent-context>summary::-webkit-details-marker{display:none}.frankie-root .frankie-agent-context>summary>svg{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-context-count{background:var(--frankie-muted);color:var(--frankie-muted-foreground);border-radius:999px;padding:2px 10px;font-size:12px}.frankie-root .frankie-context-status{color:var(--frankie-muted-foreground);align-items:center;gap:6px;font-size:12px;display:flex}.frankie-root .frankie-context-status i{background:currentColor;border-radius:50%;width:7px;height:7px}.frankie-root .frankie-context-status[data-active=true]{color:#00976b}.frankie-root .frankie-context-detail{z-index:10;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:16px;width:340px;max-width:calc(100vw - 32px);padding:18px;position:absolute;top:calc(100% + 10px);left:50%;transform:translate(-50%);box-shadow:0 12px 32px #00000016}.frankie-root .frankie-context-detail p{color:var(--frankie-muted-foreground);margin:10px 0 0;font-size:12px;line-height:1.6}.frankie-root .frankie-context-detail ul{max-height:220px;margin:12px 0;padding:0;list-style:none;overflow:auto}.frankie-root .frankie-context-detail li{border-bottom:1px solid var(--frankie-border);overflow-wrap:anywhere;justify-content:space-between;gap:12px;padding:8px 0;display:flex}.frankie-root .frankie-context-detail small{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.frankie-root.frankie-chat-panel-fill{--frankie-canvas:var(--frankie-background)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill{--frankie-canvas:color-mix(in srgb,var(--frankie-background) 60%,var(--frankie-muted))}}.frankie-root.frankie-chat-panel-fill{background:var(--frankie-canvas)}.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:44px 16px 26px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:14px max(24px,50% - 480px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-message-list{gap:38px}.frankie-root.frankie-chat-panel-fill .frankie-user-bubble{background:var(--frankie-muted);color:var(--frankie-foreground);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:24px;padding:12px 20px;font-size:15px}.frankie-root.frankie-chat-panel-fill .frankie-assistant-content{flex:1;max-width:100%;font-size:15px;line-height:1.7}.frankie-root.frankie-chat-panel-fill .frankie-assistant-message{gap:14px}.frankie-root .frankie-thinking{color:var(--frankie-muted-foreground);gap:5px}.frankie-root .frankie-thinking-label{margin-right:6px;font-size:14px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{background:0 0;border:0;flex:none;padding:16px max(24px,50% - 500px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-composer{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:28px;padding:14px;box-shadow:0 2px 4px #0000000a}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:color-mix(in srgb,var(--frankie-foreground) 32%,var(--frankie-border))}}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px color-mix(in srgb,var(--frankie-primary) 8%,transparent)}}.frankie-root.frankie-chat-panel-fill .frankie-composer-controls{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.frankie-root.frankie-chat-panel-fill .frankie-composer textarea{resize:none;width:100%;min-height:32px;max-height:140px;color:var(--frankie-foreground);box-shadow:none;background:0 0;border:0;border-radius:0;outline:none;flex:0 0 100%;order:-1;margin-bottom:4px;padding:2px 6px;font-size:16px}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Send],.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Stop]{background:var(--frankie-primary);width:42px;height:42px;color:var(--frankie-primary-foreground);border:0;border-radius:50%;margin-left:auto}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Attach\\ files]{border-radius:50%;width:42px;height:42px}.frankie-root .frankie-composer-actions{align-items:center;gap:6px;min-width:0;display:flex}.frankie-root .frankie-composer-meta{align-items:center;gap:8px;margin-top:6px;padding:0 2px;display:flex}.frankie-root .frankie-model-picker{align-items:center;min-width:0;display:inline-flex}.frankie-root .frankie-model-select{appearance:none;max-width:12rem;color:var(--frankie-muted-foreground);font:inherit;cursor:pointer;text-overflow:ellipsis;background-color:#0000;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");background-position:right 6px center;background-repeat:no-repeat;background-size:11px;border:0;border-radius:8px;padding:5px 22px 5px 8px;font-size:12px;font-weight:500;line-height:1;transition:background-color .12s,color .12s}.frankie-root .frankie-model-select:hover{background-color:var(--frankie-muted);color:var(--frankie-foreground)}.frankie-root .frankie-model-select:disabled{opacity:.5;cursor:not-allowed}.frankie-root .frankie-model-select option{color:var(--frankie-foreground);background:var(--frankie-background);font-weight:400}.frankie-root .frankie-history-desktop{background:var(--frankie-background);width:290px;padding:20px 12px}.frankie-root .frankie-history-collapsed{width:56px;padding:20px 8px}.frankie-root .frankie-new-chat{background:0 0;border:0;justify-content:flex-start;padding:8px 12px;font-size:15px}.frankie-root .frankie-history-heading{color:var(--frankie-muted-foreground);padding:0 12px;font-size:12px;font-weight:400}.frankie-root .frankie-history-list button{min-height:44px;padding:10px 12px}.frankie-root .frankie-history-list button span{font-size:14px}.frankie-root .frankie-history-list button[aria-current],.frankie-root .frankie-history-list button:hover{background:var(--frankie-muted);border-color:#0000}.frankie-root .frankie-history-list small{display:none}.frankie-root .frankie-history-group{flex-direction:column;gap:2px;display:flex}.frankie-root .frankie-history-group+.frankie-history-group{margin-top:12px}.frankie-root .frankie-history-group-label{letter-spacing:.04em;color:var(--frankie-muted-foreground);margin:0;padding:4px 12px;font-size:11px;font-weight:600}.frankie-root .frankie-page-header{background:var(--frankie-background);height:56px;min-height:56px}.frankie-root .frankie-page-header>div{min-width:0}.frankie-root .frankie-thread-title{text-overflow:ellipsis;white-space:nowrap;max-width:55vw;font-weight:500;overflow:hidden}.frankie-root .frankie-page-header button{background:0 0;border-color:#0000}.frankie-root .frankie-page-canvas>.frankie-inline{max-width:none}@media (max-width:760px){.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:20px 8px 14px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:12px 16px 16px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{padding:10px 12px calc(12px + env(safe-area-inset-bottom))}.frankie-root .frankie-agent-context>summary{gap:6px;padding:7px 9px;font-size:12px}.frankie-root .frankie-context-count{padding:2px 7px;font-size:11px}.frankie-root .frankie-context-status{gap:4px;font-size:11px}.frankie-root .frankie-agent-context>summary>svg{width:14px}.frankie-root .frankie-thread-title{max-width:42vw}}.frankie-root .frankie-agent-context>summary>svg:first-child{box-sizing:content-box;background:var(--frankie-muted);border-radius:50%;padding:4px}.frankie-root.frankie-chat-panel-fill .frankie-agent-context>summary{font-size:14px}.frankie-root .frankie-agent-context>summary>span:first-of-type{border-right:1px solid var(--frankie-border);padding-right:10px}@media (max-width:760px){.frankie-root .frankie-page-header button>span{display:none}}.frankie-root .frankie-choices{flex-direction:column;gap:8px;margin-top:12px;display:flex}.frankie-root .frankie-choice{text-align:left;cursor:pointer;border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);width:100%;color:var(--frankie-foreground);font:inherit;align-items:center;gap:12px;padding:11px 14px;font-size:14px;line-height:1.4;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-root .frankie-choice:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 55%, var(--frankie-border))}}.frankie-root .frankie-choice:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 6%, var(--frankie-background))}}.frankie-root .frankie-choice:active:not(:disabled){transform:scale(.99)}.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}.frankie-root .frankie-choice:disabled{opacity:.6;cursor:default}.frankie-root .frankie-choice-index{border:1px solid var(--frankie-border);background:var(--frankie-muted);width:24px;height:24px;color:var(--frankie-muted-foreground);border-radius:50%;flex:none;place-items:center;font-size:12px;font-weight:600;transition:background-color .15s,color .15s,border-color .15s;display:grid}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-primary);border-color:var(--frankie-primary);color:var(--frankie-primary-foreground)}.frankie-root .frankie-choice-label{flex:1;min-width:0}.frankie-root .frankie-choice-go{color:var(--frankie-muted-foreground);opacity:0;flex:none;transition:opacity .15s,transform .15s;transform:translate(-4px)}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-go{opacity:1;color:var(--frankie-primary);transform:none}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-choice,.frankie-root .frankie-choice-go,.frankie-root .frankie-choice-index{transition:none}}.frankie-root .frankie-choice-other{color:var(--frankie-muted-foreground);border-style:dashed}.frankie-root .frankie-choice-other .frankie-choice-index{background:0 0}.frankie-root .frankie-choice-other:hover:not(:disabled){color:var(--frankie-foreground)}.frankie-root .frankie-choice-other:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-muted);border-color:var(--frankie-border);color:var(--frankie-foreground)}.frankie-root .frankie-choice-hint{color:var(--frankie-muted-foreground);flex:none;font-size:12px}.frankie-root .frankie-skeleton{flex-direction:column;gap:8px;max-width:min(420px,100%);padding:4px 0 6px;display:flex}.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, var(--frankie-muted-foreground) 25%, var(--frankie-muted-foreground) 37%, var(--frankie-muted-foreground) 63%);border-radius:6px;height:12px}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 25%, color-mix(in srgb, var(--frankie-muted-foreground) 19%, transparent) 37%, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 63%)}}.frankie-root .frankie-skeleton-line{background-size:400% 100%;animation:2.2s ease-in-out infinite frankie-shimmer}.frankie-root .frankie-skeleton.is-delayed{animation:.25s .35s both frankie-skeleton-in}@keyframes frankie-skeleton-in{0%{opacity:0}to{opacity:1}}@keyframes frankie-shimmer{0%{background-position:100%}to{background-position:0}}@keyframes frankie-skeleton-pulse{0%,to{opacity:.45}50%{opacity:.85}}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-skeleton-line{background:var(--frankie-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:color-mix(in srgb, var(--frankie-muted-foreground) 16%, transparent)}}.frankie-root .frankie-skeleton-line{animation:1.6s ease-in-out infinite frankie-skeleton-pulse}}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden])){flex-wrap:wrap;align-items:center;row-gap:8px}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>textarea{flex:1 0 100%;order:-1;width:100%}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>.frankie-composer-actions{flex:auto}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>button{margin-left:auto}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}`;
1072
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-ease:initial}}}@layer theme{.frankie-root{--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--color-background:var(--frankie-background);--color-foreground:var(--frankie-foreground);--color-primary:var(--frankie-primary)}}@layer components{.frankie-page-shell{background:var(--frankie-background);height:100%;min-height:0;color:var(--frankie-foreground);flex:1;display:flex}.frankie-page-main{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.frankie-history-desktop{border-right:1px solid var(--frankie-border);background:var(--frankie-secondary);flex-direction:column;flex-shrink:0;gap:16px;width:260px;padding:20px 14px;transition:width .16s,padding .16s;display:flex;overflow:auto}.frankie-history-toggle{border:1px solid var(--frankie-border);background:var(--frankie-background);width:32px;height:32px;color:var(--frankie-muted-foreground);cursor:pointer;border-radius:8px;flex-shrink:0;justify-content:center;align-self:flex-end;align-items:center;display:flex}.frankie-history-toggle:hover{color:var(--frankie-foreground)}.frankie-history-collapsed{width:56px;padding:20px 8px;overflow:visible}.frankie-history-collapsed .frankie-history-toggle{align-self:center}.frankie-history-heading{justify-content:space-between;align-items:center;font-size:14px;display:flex}.frankie-new-chat{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;gap:8px;min-height:44px;font-weight:600;display:flex}.frankie-history-search>span{color:var(--frankie-muted-foreground);margin-bottom:6px;font-size:12px;display:block}.frankie-history-search input{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:8px;width:100%;min-height:40px;padding:8px 10px}.frankie-history-list{flex-direction:column;flex:1;gap:4px;display:flex}.frankie-history-list button{text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:8px;flex-direction:column;align-items:flex-start;gap:5px;min-height:54px;padding:10px;display:flex}.frankie-history-list button span{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:13px;overflow:hidden}.frankie-history-list small{color:var(--frankie-muted-foreground);font-size:11px}.frankie-history-list button:hover,.frankie-history-list button[aria-current]{background:var(--frankie-background);border-color:var(--frankie-border)}.frankie-history-desktop>p,.frankie-history-dialog p{color:var(--frankie-muted-foreground);font-size:13px}.frankie-header-caption{color:var(--frankie-muted-foreground);font-size:12px}.frankie-page-header button{cursor:pointer;justify-content:center;align-items:center;gap:6px;min-width:40px;min-height:40px;display:inline-flex}.frankie-chat-settings{position:relative}.frankie-chat-settings summary{cursor:pointer;border-radius:8px;place-items:center;width:40px;height:40px;list-style:none;display:grid}.frankie-chat-settings summary::-webkit-details-marker{display:none}.frankie-chat-settings>div{z-index:5;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:12px;gap:12px;width:min(280px,80vw);padding:16px;font-size:13px;display:grid;position:absolute;top:46px;right:0;box-shadow:0 10px 30px #0002}.frankie-chat-settings p{color:var(--frankie-muted-foreground);margin:0}.frankie-loaded-skills{width:100%;max-width:760px;color:var(--frankie-muted-foreground);font-size:12px}.frankie-loaded-skills summary{cursor:pointer;padding:6px 0}.frankie-loaded-skills ul{margin:0;padding:4px 0;list-style:none}.frankie-loaded-skills li{gap:8px;padding:4px 0;display:flex}.frankie-loaded-skills small{opacity:.7}.frankie-history-dialog{background:var(--frankie-secondary);width:min(320px,86vw);max-width:none;height:100dvh;max-height:none;color:var(--frankie-foreground);border:0;margin:0;padding:0}.frankie-history-dialog::backdrop{background:#0008}.frankie-history-dialog>aside{height:100%;padding:calc(20px + env(safe-area-inset-top)) 16px calc(20px + env(safe-area-inset-bottom));flex-direction:column;gap:16px;display:flex;overflow:auto}.frankie-mobile-only{display:none!important}.frankie-widget-panel{max-height:calc(100dvh - 100px - var(--frankie-lift,0px))}.frankie-root button:focus-visible,.frankie-root summary:focus-visible,.frankie-root input:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:3px}.frankie-root button:disabled{opacity:.5;cursor:not-allowed}@media (max-width:760px){.frankie-history-desktop{display:none}.frankie-mobile-only{display:inline-flex!important}.frankie-header-caption{display:none}.frankie-page-header{padding:6px 10px}.frankie-history-heading button{background:0 0;border:0;justify-content:center;align-items:center;min-width:44px;min-height:44px}.frankie-page-prompts{gap:8px}.frankie-widget-panel{width:calc(100vw - 32px)}}.frankie-root{--frankie-styles-ready:1;--frankie-background:#fff;--frankie-foreground:#0a0a0a;--frankie-primary:#171717;--frankie-primary-foreground:#fafafa;--frankie-secondary:#f5f5f5;--frankie-secondary-foreground:#171717;--frankie-muted:#f5f5f5;--frankie-muted-foreground:#737373;--frankie-border:#e5e5e5;--frankie-radius:.625rem;--frankie-font:ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;font-family:var(--frankie-font);color:var(--frankie-foreground);-webkit-font-smoothing:antialiased;line-height:1.5}.frankie-root.dark{--frankie-background:#0a0a0a;--frankie-foreground:#fafafa;--frankie-primary:#fafafa;--frankie-primary-foreground:#171717;--frankie-secondary:#262626;--frankie-secondary-foreground:#fafafa;--frankie-muted:#262626;--frankie-muted-foreground:#a3a3a3;--frankie-border:#262626}.frankie-root,.frankie-root *,.frankie-root :before,.frankie-root :after{box-sizing:border-box}.frankie-root button,.frankie-root textarea,.frankie-root input{font:inherit;color:inherit;margin:0}.frankie-root button{background-color:#0000;border:0 solid}.frankie-root textarea{background-color:var(--frankie-background)}.frankie-focus:focus-visible{outline:2px solid var(--frankie-primary);outline-offset:2px}.frankie-scroll{scrollbar-width:thin;scrollbar-color:var(--frankie-border) transparent}.frankie-prose>*+*{margin-top:.6rem}.frankie-prose p{white-space:pre-wrap;overflow-wrap:anywhere;margin:0;line-height:1.6}.frankie-prose>.frankie-h{letter-spacing:-.01em;margin-top:1.15rem;line-height:1.3}.frankie-prose>.frankie-h:first-child{margin-top:0}.frankie-prose h3.frankie-h{font-size:1.06em;font-weight:700}.frankie-prose h4.frankie-h{font-size:1em;font-weight:600}.frankie-prose h5.frankie-h{color:var(--frankie-muted-foreground);font-size:.92em;font-weight:600}.frankie-prose strong{font-weight:600}.frankie-prose ul,.frankie-prose ol{flex-direction:column;gap:.35rem;margin:0;padding-left:1.4rem;display:flex}.frankie-prose li{padding-left:.15rem;line-height:1.55}.frankie-prose li::marker{color:var(--frankie-muted-foreground)}.frankie-prose ul{list-style:outside}.frankie-prose ol{list-style:decimal}.frankie-prose a{color:var(--frankie-primary);text-underline-offset:2px;text-decoration:underline}.frankie-prose code{background-color:var(--frankie-muted);border-radius:.25rem;padding:.1em .3em;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.85em}.frankie-prose pre{border-radius:var(--frankie-radius);background-color:var(--frankie-muted);margin:0;padding:.625rem .75rem;overflow-x:auto}.frankie-prose pre code{background:0 0;padding:0}.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, var(--frankie-primary), transparent 65%), var(--frankie-background);flex-direction:column;min-width:0;display:flex;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.frankie-chat-page{background:radial-gradient(60rem 24rem at 50% -12rem, color-mix(in srgb, var(--frankie-primary) 8%, transparent), transparent 65%), var(--frankie-background)}}.frankie-chat-page{color:var(--frankie-foreground)}.frankie-page-header{border-bottom:1px solid var(--frankie-border);background:var(--frankie-background);flex:0 0 56px;justify-content:space-between;align-items:center;gap:16px;min-height:56px;padding:0 24px;display:flex}@supports (color:color-mix(in lab, red, red)){.frankie-page-header{background:color-mix(in srgb, var(--frankie-background) 92%, transparent)}}.frankie-page-header{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.frankie-page-header>div{align-items:center;gap:10px;display:flex}.frankie-page-header strong{font-size:.925rem;font-weight:650}.frankie-page-status{background:var(--frankie-primary);width:10px;height:10px;box-shadow:0 0 0 4px var(--frankie-primary);border-radius:999px}@supports (color:color-mix(in lab, red, red)){.frankie-page-status{box-shadow:0 0 0 4px color-mix(in srgb, var(--frankie-primary) 16%, transparent)}}.frankie-page-header button{border:1px solid var(--frankie-border);border-radius:calc(var(--frankie-radius) * .9);background:var(--frankie-secondary);cursor:pointer;min-height:36px;padding:0 13px}.frankie-page-header button:hover{border-color:var(--frankie-primary)}.frankie-page-canvas{flex:1;min-width:0;min-height:0;display:flex}.frankie-page-canvas>.frankie-inline{width:100%;max-width:56rem;margin:0 auto}.frankie-page-canvas .frankie-scroll{padding:2rem clamp(1rem,4vw,4rem) 1.25rem}.frankie-page-canvas .frankie-root>.border-t{background:linear-gradient(180deg, transparent, var(--frankie-background) 30%);border-top:0;padding:.75rem clamp(1rem,4vw,4rem) 1.5rem}.frankie-page-empty{text-align:center;flex-direction:column;flex-shrink:0;justify-content:safe center;align-items:center;gap:2rem;width:min(100%,44rem);min-height:100%;margin:auto;padding:clamp(2rem,7vh,4.5rem) 1rem 2rem;display:flex;container-type:inline-size}.frankie-page-welcome h1{letter-spacing:-.02em;margin:0;font-size:clamp(1.55rem,3.4vw,2rem);font-weight:700;line-height:1.15}.frankie-page-welcome p{max-width:34rem;color:var(--frankie-muted-foreground);margin:.6rem auto 0;font-size:1rem}.frankie-page-suggest{flex-direction:column;align-items:center;gap:1rem;width:100%;display:flex}.frankie-page-suggest-label{color:var(--frankie-muted-foreground);letter-spacing:.12em;text-transform:uppercase;margin:0;font-size:.72rem;font-weight:600}.frankie-page-prompts{grid-template-columns:1fr;gap:.75rem;width:100%;display:grid}@container (min-width:30rem){.frankie-page-prompts{grid-template-columns:repeat(2,minmax(0,1fr))}}.frankie-page-prompts button{border:1px solid var(--frankie-border);background:var(--frankie-background);text-align:left;cursor:pointer;border-radius:14px;align-items:flex-start;gap:.85rem;min-height:64px;padding:.9rem 1rem;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-page-prompts button:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-page-prompts button:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-page-prompts button:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 4%, var(--frankie-background))}}.frankie-page-prompts button:hover:not(:disabled){transform:translateY(-1px)}.frankie-prompt-icon{background:var(--frankie-muted);width:34px;height:34px;color:var(--frankie-foreground);border-radius:9px;flex:none;place-items:center;display:grid}.frankie-prompt-text{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-prompt-text strong{font-size:.9rem;font-weight:600;line-height:1.3}.frankie-prompt-text small{color:var(--frankie-muted-foreground);font-size:.8rem;line-height:1.35;overflow:hidden}.frankie-page-suggest-hint{color:var(--frankie-muted-foreground);margin:0;font-size:.85rem}.frankie-widget-panel .frankie-page-empty{gap:1rem;padding:1rem .25rem}.frankie-widget-panel .frankie-page-welcome h1{font-size:1.25rem}.frankie-widget-panel .frankie-page-welcome p{margin-top:.35rem;font-size:.88rem;line-height:1.45}.frankie-widget-panel .frankie-page-suggest{gap:.55rem}.frankie-widget-panel .frankie-page-suggest-label{font-size:.66rem}.frankie-widget-panel .frankie-page-prompts{flex-wrap:wrap;justify-content:center;gap:.4rem;display:flex}.frankie-widget-panel .frankie-page-prompts button{border-radius:999px;align-items:center;gap:.4rem;max-width:100%;min-height:34px;padding:.3rem .8rem .3rem .45rem}.frankie-widget-panel .frankie-prompt-icon{border-radius:999px;width:22px;height:22px}.frankie-widget-panel .frankie-prompt-icon svg{width:13px;height:13px}.frankie-widget-panel .frankie-prompt-text strong{white-space:nowrap;text-overflow:ellipsis;font-size:.82rem;font-weight:550;overflow:hidden}.frankie-widget-panel .frankie-prompt-text small,.frankie-widget-panel .frankie-page-suggest-hint{display:none}@media (max-width:640px){.frankie-page-header{flex-basis:52px;min-height:52px;padding:0 12px}.frankie-page-canvas .frankie-scroll{padding:1.25rem .75rem .5rem}.frankie-page-canvas .frankie-root>.border-t{padding:.65rem .75rem calc(.65rem + env(safe-area-inset-bottom))}}}@layer utilities;.frankie-root .\\@container{container-type:inline-size}.frankie-root .invisible{visibility:hidden}.frankie-root .visible{visibility:visible}.frankie-root .absolute{position:absolute}.frankie-root .fixed{position:fixed}.frankie-root .relative{position:relative}.frankie-root .static{position:static}.frankie-root .sticky{position:sticky}.frankie-root .isolate{isolation:isolate}.frankie-root .container{width:100%}@media (min-width:40rem){.frankie-root .container{max-width:40rem}}@media (min-width:48rem){.frankie-root .container{max-width:48rem}}@media (min-width:64rem){.frankie-root .container{max-width:64rem}}@media (min-width:80rem){.frankie-root .container{max-width:80rem}}@media (min-width:96rem){.frankie-root .container{max-width:96rem}}.frankie-root .mt-0{margin-top:0}.frankie-root .mt-0\\.5{margin-top:calc(var(--spacing) * .5)}.frankie-root .mt-1{margin-top:var(--spacing)}.frankie-root .mt-2{margin-top:calc(var(--spacing) * 2)}.frankie-root .block{display:block}.frankie-root .contents{display:contents}.frankie-root .flex{display:flex}.frankie-root .grid{display:grid}.frankie-root .hidden{display:none}.frankie-root .inline{display:inline}.frankie-root .inline-flex{display:inline-flex}.frankie-root .table{display:table}.frankie-root .size-1{width:var(--spacing);height:var(--spacing)}.frankie-root .size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.frankie-root .size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.frankie-root .size-3\\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.frankie-root .size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.frankie-root .size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.frankie-root .size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.frankie-root .size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.frankie-root .size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.frankie-root .size-full{width:100%;height:100%}.frankie-root .h-8{height:calc(var(--spacing) * 8)}.frankie-root .h-9{height:calc(var(--spacing) * 9)}.frankie-root .h-10{height:calc(var(--spacing) * 10)}.frankie-root .h-\\[32rem\\]{height:32rem}.frankie-root .h-full{height:100%}.frankie-root .h-px{height:1px}.frankie-root .min-h-7{min-height:calc(var(--spacing) * 7)}.frankie-root .min-h-\\[2\\.25rem\\]{min-height:2.25rem}.frankie-root .min-h-screen{min-height:100vh}.frankie-root .w-\\[22rem\\]{width:22rem}.frankie-root .w-full{width:100%}.frankie-root .max-w-\\[12rem\\]{max-width:12rem}.frankie-root .max-w-\\[14rem\\]{max-width:14rem}.frankie-root .max-w-\\[85\\%\\]{max-width:85%}.frankie-root .max-w-\\[calc\\(100vw-2rem\\)\\]{max-width:calc(100vw - 2rem)}.frankie-root .min-w-0{min-width:0}.frankie-root .flex-1{flex:1}.frankie-root .shrink-0{flex-shrink:0}.frankie-root .grow{flex-grow:1}.frankie-root .animate-pulse{animation:var(--animate-pulse)}.frankie-root .animate-spin{animation:var(--animate-spin)}.frankie-root .cursor-pointer{cursor:pointer}.frankie-root .resize{resize:both}.frankie-root .resize-none{resize:none}.frankie-root .list-none{list-style-type:none}.frankie-root .flex-col{flex-direction:column}.frankie-root .flex-wrap{flex-wrap:wrap}.frankie-root .items-center{align-items:center}.frankie-root .items-end{align-items:flex-end}.frankie-root .items-start{align-items:flex-start}.frankie-root .justify-center{justify-content:center}.frankie-root .justify-end{justify-content:flex-end}.frankie-root .gap-1{gap:var(--spacing)}.frankie-root .gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.frankie-root .gap-2{gap:calc(var(--spacing) * 2)}.frankie-root .gap-3{gap:calc(var(--spacing) * 3)}.frankie-root .gap-4{gap:calc(var(--spacing) * 4)}.frankie-root .truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.frankie-root .overflow-hidden{overflow:hidden}.frankie-root .overflow-y-auto{overflow-y:auto}.frankie-root .overscroll-contain{overscroll-behavior:contain}.frankie-root .rounded{border-radius:.25rem}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)\\+4px\\)\\]{border-radius:calc(var(--frankie-radius) + 4px)}.frankie-root .rounded-\\[calc\\(var\\(--frankie-radius\\)-2px\\)\\]{border-radius:calc(var(--frankie-radius) - 2px)}.frankie-root .rounded-\\[var\\(--frankie-radius\\)\\]{border-radius:var(--frankie-radius)}.frankie-root .rounded-full{border-radius:3.40282e38px}.frankie-root .rounded-md{border-radius:var(--radius-md)}.frankie-root .rounded-none{border-radius:0}.frankie-root .border{border-style:var(--tw-border-style);border-width:1px}.frankie-root .border-0{border-style:var(--tw-border-style);border-width:0}.frankie-root .border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.frankie-root .border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.frankie-root .border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.frankie-root .border-border{border-color:var(--frankie-border)}.frankie-root .border-transparent{border-color:#0000}.frankie-root .bg-background{background-color:var(--frankie-background)}.frankie-root .bg-border{background-color:var(--frankie-border)}.frankie-root .bg-emerald-500{background-color:var(--color-emerald-500)}.frankie-root .bg-emerald-500\\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-emerald-500\\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.frankie-root .bg-muted{background-color:var(--frankie-muted)}.frankie-root .bg-muted-foreground{background-color:var(--frankie-muted-foreground)}.frankie-root .bg-primary{background-color:var(--frankie-primary)}.frankie-root .bg-red-500{background-color:var(--color-red-500)}.frankie-root .bg-red-500\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.frankie-root .bg-red-500\\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.frankie-root .bg-secondary{background-color:var(--frankie-secondary)}.frankie-root .object-cover{object-fit:cover}.frankie-root .p-3{padding:calc(var(--spacing) * 3)}.frankie-root .p-4{padding:calc(var(--spacing) * 4)}.frankie-root .px-1{padding-inline:var(--spacing)}.frankie-root .px-2{padding-inline:calc(var(--spacing) * 2)}.frankie-root .px-3{padding-inline:calc(var(--spacing) * 3)}.frankie-root .px-4{padding-inline:calc(var(--spacing) * 4)}.frankie-root .px-6{padding-inline:calc(var(--spacing) * 6)}.frankie-root .py-0{padding-block:0}.frankie-root .py-0\\.5{padding-block:calc(var(--spacing) * .5)}.frankie-root .py-1{padding-block:var(--spacing)}.frankie-root .py-2{padding-block:calc(var(--spacing) * 2)}.frankie-root .py-3{padding-block:calc(var(--spacing) * 3)}.frankie-root .pl-2{padding-left:calc(var(--spacing) * 2)}.frankie-root .text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.frankie-root .text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.frankie-root .text-\\[0\\.625rem\\]{font-size:.625rem}.frankie-root .text-\\[0\\.6875rem\\]{font-size:.6875rem}.frankie-root .text-\\[11px\\]{font-size:11px}.frankie-root .leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.frankie-root .font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.frankie-root .font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.frankie-root .whitespace-nowrap{white-space:nowrap}.frankie-root .text-emerald-600{color:var(--color-emerald-600)}.frankie-root .text-foreground{color:var(--frankie-foreground)}.frankie-root .text-muted-foreground{color:var(--frankie-muted-foreground)}.frankie-root .text-primary{color:var(--frankie-primary)}.frankie-root .text-primary-foreground{color:var(--frankie-primary-foreground)}.frankie-root .text-red-600{color:var(--color-red-600)}.frankie-root .text-secondary-foreground{color:var(--frankie-secondary-foreground)}.frankie-root .italic{font-style:italic}.frankie-root .underline-offset-4{text-underline-offset:4px}.frankie-root .opacity-60{opacity:.6}.frankie-root .opacity-70{opacity:.7}.frankie-root .shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .outline{outline-style:var(--tw-outline-style);outline-width:1px}.frankie-root .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.frankie-root .ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.frankie-root .select-all{-webkit-user-select:all;user-select:all}.frankie-root .placeholder\\:text-muted-foreground::placeholder{color:var(--frankie-muted-foreground)}@media (hover:hover){.frankie-root .hover\\:border-border:hover{border-color:var(--frankie-border)}.frankie-root .hover\\:bg-muted:hover{background-color:var(--frankie-muted)}.frankie-root .hover\\:text-foreground:hover{color:var(--frankie-foreground)}.frankie-root .hover\\:underline:hover{text-decoration-line:underline}.frankie-root .hover\\:opacity-90:hover{opacity:.9}.frankie-root .hover\\:opacity-100:hover{opacity:1}}.frankie-root .focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.frankie-root .focus-visible\\:ring-primary:focus-visible{--tw-ring-color:var(--frankie-primary)}.frankie-root .focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.frankie-root .disabled\\:pointer-events-none:disabled{pointer-events:none}.frankie-root .disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.frankie-root .disabled\\:opacity-50:disabled{opacity:.5}.frankie-root .dark\\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.frankie-root .dark\\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.frankie-root .\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.frankie-root .\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.frankie-root .\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.frankie-root .\\[\\&\\:\\:-webkit-details-marker\\]\\:hidden::-webkit-details-marker{display:none}.frankie-root.frankie-chat-panel{min-height:0;position:relative}.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px var(--frankie-primary), 0 12px 28px -12px #0f172a47, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel{box-shadow:0 32px 72px -18px color-mix(in srgb, var(--frankie-primary) 22%, #0f172a6b), 0 12px 28px -12px #0f172a47, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 8%, transparent)}}.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-widget-panel.dark{box-shadow:0 34px 80px -16px #000000b8, 0 14px 32px -12px #0009, 0 0 0 1px color-mix(in srgb, var(--frankie-foreground) 12%, transparent)}}.frankie-root .frankie-agent-context-wrap{flex:none;justify-content:center;padding:12px 10px;display:flex}.frankie-root .frankie-agent-context{max-width:100%;color:var(--frankie-foreground);font-size:13px;position:relative}.frankie-root .frankie-agent-context>summary{border:1px solid var(--frankie-border);background:var(--frankie-background);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:10px;min-height:44px;padding:7px 13px;list-style:none;display:flex;box-shadow:0 1px 3px #0000000d}.frankie-root .frankie-agent-context>summary::-webkit-details-marker{display:none}.frankie-root .frankie-agent-context>summary>svg{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-context-count{background:var(--frankie-muted);color:var(--frankie-muted-foreground);border-radius:999px;padding:2px 10px;font-size:12px}.frankie-root .frankie-context-status{color:var(--frankie-muted-foreground);align-items:center;gap:6px;font-size:12px;display:flex}.frankie-root .frankie-context-status i{background:currentColor;border-radius:50%;width:7px;height:7px}.frankie-root .frankie-context-status[data-active=true]{color:#00976b}.frankie-root .frankie-context-detail{z-index:10;border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:16px;width:340px;max-width:calc(100vw - 32px);padding:18px;position:absolute;top:calc(100% + 10px);left:50%;transform:translate(-50%);box-shadow:0 12px 32px #00000016}.frankie-root .frankie-context-detail p{color:var(--frankie-muted-foreground);margin:10px 0 0;font-size:12px;line-height:1.6}.frankie-root .frankie-context-detail ul{max-height:220px;margin:12px 0;padding:0;list-style:none;overflow:auto}.frankie-root .frankie-context-detail li{border-bottom:1px solid var(--frankie-border);overflow-wrap:anywhere;justify-content:space-between;gap:12px;padding:8px 0;display:flex}.frankie-root .frankie-context-detail small{color:var(--frankie-muted-foreground);flex:none}.frankie-root .frankie-sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.frankie-root.frankie-chat-panel-fill{--frankie-canvas:var(--frankie-background)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill{--frankie-canvas:color-mix(in srgb,var(--frankie-background) 60%,var(--frankie-muted))}}.frankie-root.frankie-chat-panel-fill{background:var(--frankie-canvas)}.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:44px 16px 26px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:14px max(24px,50% - 480px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-message-list{gap:38px}.frankie-root.frankie-chat-panel-fill .frankie-user-bubble{background:var(--frankie-muted);color:var(--frankie-foreground);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:24px;padding:12px 20px;font-size:15px}.frankie-root.frankie-chat-panel-fill .frankie-assistant-content{flex:1;max-width:100%;font-size:15px;line-height:1.7}.frankie-root.frankie-chat-panel-fill .frankie-assistant-message{gap:14px}.frankie-root .frankie-thinking{color:var(--frankie-muted-foreground);gap:5px}.frankie-root .frankie-thinking-label{margin-right:6px;font-size:14px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{background:0 0;border:0;flex:none;padding:16px max(24px,50% - 500px) 24px}.frankie-root.frankie-chat-panel-fill .frankie-composer{border:1px solid var(--frankie-border);background:var(--frankie-background);border-radius:28px;padding:14px;box-shadow:0 2px 4px #0000000a}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:var(--frankie-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{border-color:color-mix(in srgb,var(--frankie-foreground) 32%,var(--frankie-border))}}.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root.frankie-chat-panel-fill .frankie-composer:focus-within{box-shadow:0 0 0 2px color-mix(in srgb,var(--frankie-primary) 8%,transparent)}}.frankie-root.frankie-chat-panel-fill .frankie-composer-controls{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.frankie-root.frankie-chat-panel-fill .frankie-composer textarea{resize:none;width:100%;min-height:32px;max-height:140px;color:var(--frankie-foreground);box-shadow:none;background:0 0;border:0;border-radius:0;outline:none;flex:0 0 100%;order:-1;margin-bottom:4px;padding:2px 6px;font-size:16px}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Send],.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Stop]{background:var(--frankie-primary);width:42px;height:42px;color:var(--frankie-primary-foreground);border:0;border-radius:50%;margin-left:auto}.frankie-root.frankie-chat-panel-fill .frankie-composer button[aria-label=Attach\\ files]{border-radius:50%;width:42px;height:42px}.frankie-root .frankie-composer-actions{align-items:center;gap:6px;min-width:0;display:flex}.frankie-root .frankie-composer-meta{align-items:center;gap:8px;margin-top:6px;padding:0 2px;display:flex}.frankie-root .frankie-model-picker{align-items:center;min-width:0;display:inline-flex}.frankie-root .frankie-model-select{appearance:none;max-width:12rem;color:var(--frankie-muted-foreground);font:inherit;cursor:pointer;text-overflow:ellipsis;background-color:#0000;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");background-position:right 6px center;background-repeat:no-repeat;background-size:11px;border:0;border-radius:8px;padding:5px 22px 5px 8px;font-size:12px;font-weight:500;line-height:1;transition:background-color .12s,color .12s}.frankie-root .frankie-model-select:hover{background-color:var(--frankie-muted);color:var(--frankie-foreground)}.frankie-root .frankie-model-select:disabled{opacity:.5;cursor:not-allowed}.frankie-root .frankie-model-select option{color:var(--frankie-foreground);background:var(--frankie-background);font-weight:400}.frankie-root .frankie-history-desktop{background:var(--frankie-background);width:290px;padding:20px 12px}.frankie-root .frankie-history-collapsed{width:56px;padding:20px 8px}.frankie-root .frankie-new-chat{background:0 0;border:0;justify-content:flex-start;padding:8px 12px;font-size:15px}.frankie-root .frankie-history-heading{color:var(--frankie-muted-foreground);padding:0 12px;font-size:12px;font-weight:400}.frankie-root .frankie-history-list button{min-height:44px;padding:10px 12px}.frankie-root .frankie-history-list button span{font-size:14px}.frankie-root .frankie-history-list button[aria-current],.frankie-root .frankie-history-list button:hover{background:var(--frankie-muted);border-color:#0000}.frankie-root .frankie-history-list small{display:none}.frankie-root .frankie-history-group{flex-direction:column;gap:2px;display:flex}.frankie-root .frankie-history-group+.frankie-history-group{margin-top:12px}.frankie-root .frankie-history-group-label{letter-spacing:.04em;color:var(--frankie-muted-foreground);margin:0;padding:4px 12px;font-size:11px;font-weight:600}.frankie-root .frankie-page-header{background:var(--frankie-background);height:56px;min-height:56px}.frankie-root .frankie-page-header>div{min-width:0}.frankie-root .frankie-thread-title{text-overflow:ellipsis;white-space:nowrap;max-width:55vw;font-weight:500;overflow:hidden}.frankie-root .frankie-page-header button{background:0 0;border-color:#0000}.frankie-root .frankie-page-canvas>.frankie-inline{max-width:none}@media (max-width:760px){.frankie-root.frankie-chat-panel-fill .frankie-agent-context-wrap{padding:20px 8px 14px}.frankie-root.frankie-chat-panel-fill .frankie-transcript{padding:12px 16px 16px}.frankie-root.frankie-chat-panel-fill .frankie-composer-footer{padding:10px 12px calc(12px + env(safe-area-inset-bottom))}.frankie-root .frankie-agent-context>summary{gap:6px;padding:7px 9px;font-size:12px}.frankie-root .frankie-context-count{padding:2px 7px;font-size:11px}.frankie-root .frankie-context-status{gap:4px;font-size:11px}.frankie-root .frankie-agent-context>summary>svg{width:14px}.frankie-root .frankie-thread-title{max-width:42vw}}.frankie-root .frankie-agent-context>summary>svg:first-child{box-sizing:content-box;background:var(--frankie-muted);border-radius:50%;padding:4px}.frankie-root.frankie-chat-panel-fill .frankie-agent-context>summary{font-size:14px}.frankie-root .frankie-agent-context>summary>span:first-of-type{border-right:1px solid var(--frankie-border);padding-right:10px}@media (max-width:760px){.frankie-root .frankie-page-header button>span{display:none}}.frankie-root .frankie-choices{flex-direction:column;gap:8px;margin-top:12px;display:flex}.frankie-root .frankie-choice{text-align:left;cursor:pointer;border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);width:100%;color:var(--frankie-foreground);font:inherit;align-items:center;gap:12px;padding:11px 14px;font-size:14px;line-height:1.4;transition:border-color .15s,background-color .15s,transform .12s;display:flex}.frankie-root .frankie-choice:hover:not(:disabled){border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){border-color:color-mix(in srgb, var(--frankie-primary) 55%, var(--frankie-border))}}.frankie-root .frankie-choice:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 6%, var(--frankie-background))}}.frankie-root .frankie-choice:active:not(:disabled){transform:scale(.99)}.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-choice:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}.frankie-root .frankie-choice:disabled{opacity:.6;cursor:default}.frankie-root .frankie-choice-index{border:1px solid var(--frankie-border);background:var(--frankie-muted);width:24px;height:24px;color:var(--frankie-muted-foreground);border-radius:50%;flex:none;place-items:center;font-size:12px;font-weight:600;transition:background-color .15s,color .15s,border-color .15s;display:grid}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-primary);border-color:var(--frankie-primary);color:var(--frankie-primary-foreground)}.frankie-root .frankie-choice-label{flex:1;min-width:0}.frankie-root .frankie-choice-go{color:var(--frankie-muted-foreground);opacity:0;flex:none;transition:opacity .15s,transform .15s;transform:translate(-4px)}.frankie-root .frankie-choice:hover:not(:disabled) .frankie-choice-go{opacity:1;color:var(--frankie-primary);transform:none}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-choice,.frankie-root .frankie-choice-go,.frankie-root .frankie-choice-index{transition:none}}.frankie-root .frankie-choice-other{color:var(--frankie-muted-foreground);border-style:dashed}.frankie-root .frankie-choice-other .frankie-choice-index{background:0 0}.frankie-root .frankie-choice-other:hover:not(:disabled){color:var(--frankie-foreground)}.frankie-root .frankie-choice-other:hover:not(:disabled) .frankie-choice-index{background:var(--frankie-muted);border-color:var(--frankie-border);color:var(--frankie-foreground)}.frankie-root .frankie-choice-hint{color:var(--frankie-muted-foreground);flex:none;font-size:12px}.frankie-root .frankie-skeleton{flex-direction:column;gap:8px;max-width:min(420px,100%);padding:4px 0 6px;display:flex}.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, var(--frankie-muted-foreground) 25%, var(--frankie-muted-foreground) 37%, var(--frankie-muted-foreground) 63%);border-radius:6px;height:12px}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:linear-gradient(90deg, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 25%, color-mix(in srgb, var(--frankie-muted-foreground) 19%, transparent) 37%, color-mix(in srgb, var(--frankie-muted-foreground) 11%, transparent) 63%)}}.frankie-root .frankie-skeleton-line{background-size:400% 100%;animation:2.2s ease-in-out infinite frankie-shimmer}.frankie-root .frankie-skeleton.is-delayed{animation:.25s .35s both frankie-skeleton-in}@keyframes frankie-skeleton-in{0%{opacity:0}to{opacity:1}}@keyframes frankie-shimmer{0%{background-position:100%}to{background-position:0}}@keyframes frankie-skeleton-pulse{0%,to{opacity:.45}50%{opacity:.85}}@media (prefers-reduced-motion:reduce){.frankie-root .frankie-skeleton-line{background:var(--frankie-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-skeleton-line{background:color-mix(in srgb, var(--frankie-muted-foreground) 16%, transparent)}}.frankie-root .frankie-skeleton-line{animation:1.6s ease-in-out infinite frankie-skeleton-pulse}}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden])){flex-wrap:wrap;align-items:center;row-gap:8px}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>textarea{flex:1 0 100%;order:-1;width:100%}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>.frankie-composer-actions{flex:auto}.frankie-root:not(.frankie-chat-panel-fill) .frankie-composer-controls:has(.frankie-composer-actions>:not(input[hidden]))>button{margin-left:auto}.frankie-root .frankie-action{border:1px solid var(--frankie-border);border-radius:var(--frankie-radius);background:var(--frankie-background);color:var(--frankie-foreground);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;font-size:14px;line-height:1.4;display:flex}.frankie-root .frankie-action.is-pending{border-color:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action.is-pending{border-color:color-mix(in srgb, var(--frankie-primary) 45%, var(--frankie-border))}}.frankie-root .frankie-action.is-pending{background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action.is-pending{background:color-mix(in srgb, var(--frankie-primary) 5%, var(--frankie-background))}}.frankie-root .frankie-action-head{align-items:flex-start;gap:10px;display:flex}.frankie-root .frankie-action-icon{color:var(--frankie-primary);flex-shrink:0;margin-top:2px}.frankie-root .frankie-action-title{flex-direction:column;gap:2px;min-width:0;display:flex}.frankie-root .frankie-action-title strong{overflow-wrap:anywhere;font-weight:600}.frankie-root .frankie-action-title span{color:var(--frankie-muted-foreground);font-size:12px}.frankie-root .frankie-action-route{border-radius:calc(var(--frankie-radius) * .6);background:var(--frankie-muted);overflow-wrap:anywhere;padding:6px 8px;font-size:12px;display:block}.frankie-root .frankie-action-route span{font-weight:600}.frankie-root .frankie-action-fields{gap:6px;margin:0;display:grid}.frankie-root .frankie-action-fields>div{grid-template-columns:minmax(0,35%) minmax(0,1fr);gap:10px;display:grid}.frankie-root .frankie-action-fields dt{color:var(--frankie-muted-foreground);overflow-wrap:anywhere;font-size:12px}.frankie-root .frankie-action-fields dd{white-space:pre-wrap;overflow-wrap:anywhere;max-height:8.5em;margin:0;font-size:13px;overflow:auto}.frankie-root .frankie-action-buttons{flex-wrap:wrap;gap:8px;display:flex}.frankie-root .frankie-action-buttons button{cursor:pointer;font:inherit;border-radius:var(--frankie-radius);border:1px solid var(--frankie-border);align-items:center;gap:6px;padding:7px 14px;font-size:14px;font-weight:500;transition:background-color .15s,border-color .15s;display:inline-flex}.frankie-root .frankie-action-approve{background:var(--frankie-primary);color:var(--frankie-primary-foreground);border-color:var(--frankie-primary)}.frankie-root .frankie-action-approve:hover:not(:disabled){background:var(--frankie-primary)}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action-approve:hover:not(:disabled){background:color-mix(in srgb, var(--frankie-primary) 88%, black)}}.frankie-root .frankie-action-cancel{background:var(--frankie-background);color:var(--frankie-foreground)}.frankie-root .frankie-action-cancel:hover:not(:disabled){background:var(--frankie-muted)}.frankie-root .frankie-action-buttons button:disabled{opacity:.55;cursor:not-allowed}.frankie-root .frankie-action-buttons button:focus-visible{box-shadow:0 0 0 2px var(--frankie-primary);outline:none}@supports (color:color-mix(in lab, red, red)){.frankie-root .frankie-action-buttons button:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--frankie-primary) 40%, transparent)}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}`;
1040
1073
 
1041
1074
  // src/lib/ensure-frankie-styles.ts
1042
1075
  var STYLE_ELEMENT_ID = "frankie-fallback-styles";
@@ -1110,8 +1143,8 @@ function bottomObstruction(root, position, offset) {
1110
1143
  seen.add(bar);
1111
1144
  const rect = bar.getBoundingClientRect();
1112
1145
  const anchoredToBottom = rect.bottom >= height - 4;
1113
- const short = rect.height > 0 && rect.height < height * 0.4;
1114
- if (anchoredToBottom && short) lift = Math.max(lift, height - rect.top);
1146
+ const short2 = rect.height > 0 && rect.height < height * 0.4;
1147
+ if (anchoredToBottom && short2) lift = Math.max(lift, height - rect.top);
1115
1148
  }
1116
1149
  }
1117
1150
  return Math.round(lift);
@@ -1197,7 +1230,7 @@ function Button({ className, variant, size, asChild = false, ...props }) {
1197
1230
  }
1198
1231
 
1199
1232
  // src/components/chat/ChatPanel.tsx
1200
- var import_lucide_react7 = require("lucide-react");
1233
+ var import_lucide_react8 = require("lucide-react");
1201
1234
  var import_react10 = require("react");
1202
1235
 
1203
1236
  // src/components/ui/avatar.tsx
@@ -1573,7 +1606,7 @@ function readAsBase64(file) {
1573
1606
  }
1574
1607
 
1575
1608
  // src/components/chat/MessageBubble.tsx
1576
- var import_lucide_react6 = require("lucide-react");
1609
+ var import_lucide_react7 = require("lucide-react");
1577
1610
  var import_react9 = require("react");
1578
1611
 
1579
1612
  // src/lib/choices.ts
@@ -1594,9 +1627,68 @@ function parseOptionLines(block) {
1594
1627
  return block.split("\n").map((line) => line.trim().replace(/^([-*+]|\d+[.)])\s+/, "").trim()).filter(Boolean);
1595
1628
  }
1596
1629
 
1597
- // src/components/chat/Choices.tsx
1630
+ // src/components/chat/ActionConfirm.tsx
1598
1631
  var import_lucide_react4 = require("lucide-react");
1599
1632
  var import_jsx_runtime10 = require("react/jsx-runtime");
1633
+ function ActionConfirm({
1634
+ action,
1635
+ onAnswer,
1636
+ disabled,
1637
+ live
1638
+ }) {
1639
+ const pending = action.state === "pending";
1640
+ const fields = inputFields(action.preview.input);
1641
+ const status = pending ? live ? void 0 : "Not run" : action.state === "approved" ? "Approved" : "Cancelled";
1642
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "frankie-action" + (pending && live ? " is-pending" : ""), role: "group", "aria-label": `Approve: ${action.label}`, children: [
1643
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "frankie-action-head", children: [
1644
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.ShieldAlert, { className: "frankie-action-icon size-4", "aria-hidden": true }),
1645
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "frankie-action-title", children: [
1646
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: action.label }),
1647
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: pending && live ? "Needs your approval before it runs" : status })
1648
+ ] })
1649
+ ] }),
1650
+ action.preview.method && action.preview.path ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("code", { className: "frankie-action-route", children: [
1651
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: action.preview.method }),
1652
+ " ",
1653
+ action.preview.path
1654
+ ] }) : null,
1655
+ fields.length ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dl", { className: "frankie-action-fields", children: fields.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1656
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dt", { children: key }),
1657
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("dd", { children: value })
1658
+ ] }, key)) }) : null,
1659
+ pending && live && onAnswer ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "frankie-action-buttons", children: [
1660
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", className: "frankie-action-approve", disabled, onClick: () => onAnswer(action.toolUseId, true), children: [
1661
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.Check, { className: "size-4", "aria-hidden": true }),
1662
+ " Approve"
1663
+ ] }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", className: "frankie-action-cancel", disabled, onClick: () => onAnswer(action.toolUseId, false), children: [
1665
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.X, { className: "size-4", "aria-hidden": true }),
1666
+ " Cancel"
1667
+ ] })
1668
+ ] }) : null
1669
+ ] });
1670
+ }
1671
+ function inputFields(input) {
1672
+ if (input === void 0 || input === null) return [];
1673
+ if (typeof input !== "object" || Array.isArray(input)) return [["input", short(input)]];
1674
+ const rows = [];
1675
+ for (const [key, value] of Object.entries(input)) {
1676
+ if (value === void 0) continue;
1677
+ if (key === "body" && value && typeof value === "object" && !Array.isArray(value)) {
1678
+ for (const [field, inner] of Object.entries(value)) rows.push([field, short(inner)]);
1679
+ continue;
1680
+ }
1681
+ rows.push([key, short(value)]);
1682
+ }
1683
+ return rows;
1684
+ }
1685
+ function short(value) {
1686
+ return typeof value === "string" ? value : JSON.stringify(value, null, 1);
1687
+ }
1688
+
1689
+ // src/components/chat/Choices.tsx
1690
+ var import_lucide_react5 = require("lucide-react");
1691
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1600
1692
  function Choices({
1601
1693
  options,
1602
1694
  onPick,
@@ -1604,8 +1696,8 @@ function Choices({
1604
1696
  disabled
1605
1697
  }) {
1606
1698
  if (options.length === 0) return null;
1607
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "frankie-choices", role: "group", "aria-label": "Choose an option", children: [
1608
- options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1699
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "frankie-choices", role: "group", "aria-label": "Choose an option", children: [
1700
+ options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1609
1701
  "button",
1610
1702
  {
1611
1703
  type: "button",
@@ -1613,14 +1705,14 @@ function Choices({
1613
1705
  disabled,
1614
1706
  onClick: () => onPick(option),
1615
1707
  children: [
1616
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "frankie-choice-index", "aria-hidden": true, children: index + 1 }),
1617
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "frankie-choice-label", children: option }),
1618
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.ArrowRight, { className: "frankie-choice-go size-4", "aria-hidden": true })
1708
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "frankie-choice-index", "aria-hidden": true, children: index + 1 }),
1709
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "frankie-choice-label", children: option }),
1710
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.ArrowRight, { className: "frankie-choice-go size-4", "aria-hidden": true })
1619
1711
  ]
1620
1712
  },
1621
1713
  `${index}-${option}`
1622
1714
  )),
1623
- onSomethingElse ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1715
+ onSomethingElse ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1624
1716
  "button",
1625
1717
  {
1626
1718
  type: "button",
@@ -1628,9 +1720,9 @@ function Choices({
1628
1720
  disabled,
1629
1721
  onClick: onSomethingElse,
1630
1722
  children: [
1631
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "frankie-choice-index", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.PencilLine, { className: "size-3.5" }) }),
1632
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "frankie-choice-label", children: "Something else\u2026" }),
1633
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "frankie-choice-hint", "aria-hidden": true, children: "Type your own" })
1723
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "frankie-choice-index", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.PencilLine, { className: "size-3.5" }) }),
1724
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "frankie-choice-label", children: "Something else\u2026" }),
1725
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "frankie-choice-hint", "aria-hidden": true, children: "Type your own" })
1634
1726
  ]
1635
1727
  }
1636
1728
  ) : null
@@ -1639,10 +1731,10 @@ function Choices({
1639
1731
 
1640
1732
  // src/components/chat/Markdown.tsx
1641
1733
  var import_react8 = require("react");
1642
- var import_jsx_runtime11 = require("react/jsx-runtime");
1734
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1643
1735
  var Markdown = (0, import_react8.memo)(function Markdown2({ text, className }) {
1644
1736
  const blocks = (0, import_react8.useMemo)(() => renderBlocks(text), [text]);
1645
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: cn("frankie-prose", className), children: blocks });
1737
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("frankie-prose", className), children: blocks });
1646
1738
  });
1647
1739
  function renderBlocks(text) {
1648
1740
  const lines = text.split("\n");
@@ -1652,13 +1744,13 @@ function renderBlocks(text) {
1652
1744
  let code = null;
1653
1745
  const flushParagraph = () => {
1654
1746
  if (paragraph.length === 0) return;
1655
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
1747
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
1656
1748
  paragraph = [];
1657
1749
  };
1658
1750
  const flushList = () => {
1659
1751
  if (!list) return;
1660
- const items = list.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { children: renderInline(item) }, index));
1661
- blocks.push(list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { children: items }, `l${blocks.length}`));
1752
+ const items = list.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("li", { children: renderInline(item) }, index));
1753
+ blocks.push(list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { children: items }, `l${blocks.length}`));
1662
1754
  list = null;
1663
1755
  };
1664
1756
  for (const line of lines) {
@@ -1666,7 +1758,7 @@ function renderBlocks(text) {
1666
1758
  if (fence) {
1667
1759
  if (code) {
1668
1760
  blocks.push(
1669
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1761
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1670
1762
  );
1671
1763
  code = null;
1672
1764
  } else {
@@ -1703,7 +1795,7 @@ function renderBlocks(text) {
1703
1795
  flushList();
1704
1796
  const level = (heading[1] ?? "#").length;
1705
1797
  const Tag = level <= 1 ? "h3" : level === 2 ? "h4" : "h5";
1706
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Tag, { className: "frankie-h", children: renderInline(heading[2] ?? "") }, `h${blocks.length}`));
1798
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Tag, { className: "frankie-h", children: renderInline(heading[2] ?? "") }, `h${blocks.length}`));
1707
1799
  continue;
1708
1800
  }
1709
1801
  flushList();
@@ -1711,7 +1803,7 @@ function renderBlocks(text) {
1711
1803
  }
1712
1804
  if (code) {
1713
1805
  blocks.push(
1714
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1806
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1715
1807
  );
1716
1808
  }
1717
1809
  flushParagraph();
@@ -1726,30 +1818,30 @@ function renderInline(text) {
1726
1818
  const token = match[0];
1727
1819
  const start = match.index;
1728
1820
  if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
1729
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react8.Fragment, { children: renderToken(token) }, start));
1821
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react8.Fragment, { children: renderToken(token) }, start));
1730
1822
  lastIndex = start + token.length;
1731
1823
  }
1732
1824
  if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
1733
1825
  return nodes;
1734
1826
  }
1735
1827
  function renderToken(token) {
1736
- if (token.startsWith("**")) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { children: token.slice(2, -2) });
1737
- if (token.startsWith("*")) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("em", { children: token.slice(1, -1) });
1738
- if (token.startsWith("`")) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: token.slice(1, -1) });
1828
+ if (token.startsWith("**")) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: token.slice(2, -2) });
1829
+ if (token.startsWith("*")) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("em", { children: token.slice(1, -1) });
1830
+ if (token.startsWith("`")) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { children: token.slice(1, -1) });
1739
1831
  const link = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(token);
1740
1832
  const href = link ? link[2] ?? "" : token;
1741
1833
  const label = link ? link[1] ?? "" : token;
1742
- if (!/^(https?:\/\/|\/)/.test(href)) return token;
1743
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1834
+ if (!/^(https?:\/\/|\/(?![\/\\]))/.test(href)) return token;
1835
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1744
1836
  }
1745
1837
 
1746
1838
  // src/components/chat/ToolActivityList.tsx
1747
- var import_lucide_react5 = require("lucide-react");
1839
+ var import_lucide_react6 = require("lucide-react");
1748
1840
  var import_core = require("@frankieai/core");
1749
1841
 
1750
1842
  // src/components/ui/badge.tsx
1751
1843
  var import_class_variance_authority2 = require("class-variance-authority");
1752
- var import_jsx_runtime12 = require("react/jsx-runtime");
1844
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1753
1845
  var badgeVariants = (0, import_class_variance_authority2.cva)(
1754
1846
  "inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[0.6875rem] font-medium",
1755
1847
  {
@@ -1769,46 +1861,46 @@ function Badge({
1769
1861
  variant,
1770
1862
  ...props
1771
1863
  }) {
1772
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: cn(badgeVariants({ variant }), className), ...props });
1864
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: cn(badgeVariants({ variant }), className), ...props });
1773
1865
  }
1774
1866
 
1775
1867
  // src/components/chat/ToolActivityList.tsx
1776
- var import_jsx_runtime13 = require("react/jsx-runtime");
1868
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1777
1869
  function ToolActivityList({ tools, renderTool }) {
1778
1870
  if (tools.length === 0) return null;
1779
1871
  const running = tools.some((tool) => tool.status === "running");
1780
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1781
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("summary", { className: "inline-flex min-h-7 cursor-pointer list-none items-center gap-1.5 rounded-md px-1 text-xs font-medium text-muted-foreground hover:bg-muted hover:text-foreground [&::-webkit-details-marker]:hidden", children: [
1782
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1783
- running ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.Loader2, { className: "size-3.5 animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.Wrench, { className: "size-3.5", "aria-hidden": "true" }),
1784
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: running ? "Working" : "Activity" }),
1785
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "text-[11px]", children: [
1872
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1873
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("summary", { className: "inline-flex min-h-7 cursor-pointer list-none items-center gap-1.5 rounded-md px-1 text-xs font-medium text-muted-foreground hover:bg-muted hover:text-foreground [&::-webkit-details-marker]:hidden", children: [
1874
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1875
+ running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Loader2, { className: "size-3.5 animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Wrench, { className: "size-3.5", "aria-hidden": "true" }),
1876
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: running ? "Working" : "Activity" }),
1877
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "text-[11px]", children: [
1786
1878
  "\xB7 ",
1787
1879
  tools.length,
1788
1880
  " tool call",
1789
1881
  tools.length === 1 ? "" : "s"
1790
1882
  ] })
1791
1883
  ] }),
1792
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ToolActivityRow, { tool }) }, tool.id)) })
1884
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityRow, { tool }) }, tool.id)) })
1793
1885
  ] });
1794
1886
  }
1795
1887
  function ToolActivityRow({ tool }) {
1796
1888
  const isSkill = tool.name === import_core.SKILL_TOOL_NAME;
1797
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1798
- isSkill && tool.status !== "running" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.Sparkles, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ToolIcon, { status: tool.status }),
1799
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate", children: tool.label })
1889
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1890
+ isSkill && tool.status !== "running" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Sparkles, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolIcon, { status: tool.status }),
1891
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate", children: tool.label })
1800
1892
  ] });
1801
1893
  }
1802
1894
  function ToolIcon({ status }) {
1803
1895
  switch (status) {
1804
1896
  case "running":
1805
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1897
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1806
1898
  case "done":
1807
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.Check, { className: "size-3", "aria-hidden": "true" });
1899
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Check, { className: "size-3", "aria-hidden": "true" });
1808
1900
  case "denied":
1809
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.ShieldAlert, { className: "size-3", "aria-hidden": "true" });
1901
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.ShieldAlert, { className: "size-3", "aria-hidden": "true" });
1810
1902
  default:
1811
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { className: "size-3", "aria-hidden": "true" });
1903
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.X, { className: "size-3", "aria-hidden": "true" });
1812
1904
  }
1813
1905
  }
1814
1906
  function badgeVariant(status) {
@@ -1819,7 +1911,7 @@ function badgeVariant(status) {
1819
1911
  }
1820
1912
 
1821
1913
  // src/components/chat/MessageBubble.tsx
1822
- var import_jsx_runtime14 = require("react/jsx-runtime");
1914
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1823
1915
  var MessageBubble = (0, import_react9.memo)(function MessageBubble2({
1824
1916
  message,
1825
1917
  assistantName,
@@ -1829,40 +1921,50 @@ var MessageBubble = (0, import_react9.memo)(function MessageBubble2({
1829
1921
  onChoose,
1830
1922
  onRequestInput,
1831
1923
  active,
1832
- busy
1924
+ busy,
1925
+ onAction
1833
1926
  }) {
1834
1927
  if (message.role === "user") {
1835
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "frankie-user-message flex flex-col items-end gap-1", children: [
1836
- message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1928
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-user-message flex flex-col items-end gap-1", children: [
1929
+ message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1837
1930
  "span",
1838
1931
  {
1839
1932
  className: "inline-flex max-w-[12rem] items-center gap-1 rounded-[var(--frankie-radius)] border border-border bg-muted px-2 py-1 text-xs",
1840
1933
  children: [
1841
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
1842
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate", children: file.name })
1934
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react7.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
1935
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate", children: file.name })
1843
1936
  ]
1844
1937
  },
1845
1938
  `${file.name}-${index}`
1846
1939
  )) }) : null,
1847
- message.text ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1848
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "frankie-user-bubble rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1849
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageCopyButton, { text: message.text })
1940
+ message.text ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1941
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "frankie-user-bubble rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1942
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageCopyButton, { text: message.text })
1850
1943
  ] }) : null
1851
1944
  ] });
1852
1945
  }
1853
1946
  const { body, options } = extractChoices(message.text);
1854
1947
  const showChoices = Boolean(active && onChoose && options && message.status === "done");
1855
1948
  const waiting = message.status === "streaming" && body.length === 0 && message.tools.length === 0;
1856
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "frankie-assistant-message flex gap-2", children: [
1857
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1858
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1859
- body ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageCopyButton, { text: body }) : null
1949
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-assistant-message flex gap-2", children: [
1950
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1951
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1952
+ body ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageCopyButton, { text: body }) : null
1860
1953
  ] }),
1861
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "frankie-assistant-content min-w-0 max-w-[85%]", children: [
1862
- message.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "rounded-[var(--frankie-radius)] bg-red-500/10 px-3 py-2 text-sm text-red-600 dark:text-red-400", children: message.error }) : body ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Markdown, { text: body, className: "text-sm" }) : null,
1863
- showChoices ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Choices, { options: options ?? [], onPick: onChoose, ...onRequestInput ? { onSomethingElse: onRequestInput } : {}, disabled: busy }) : null,
1864
- showToolActivity ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null,
1865
- waiting ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Thinking, { delayed: true }) : null
1954
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-assistant-content min-w-0 max-w-[85%]", children: [
1955
+ message.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "rounded-[var(--frankie-radius)] bg-red-500/10 px-3 py-2 text-sm text-red-600 dark:text-red-400", children: message.error }) : body ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Markdown, { text: body, className: "text-sm" }) : null,
1956
+ message.action ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1957
+ ActionConfirm,
1958
+ {
1959
+ action: message.action,
1960
+ live: Boolean(active),
1961
+ disabled: busy || message.status === "streaming",
1962
+ ...onAction ? { onAnswer: onAction } : {}
1963
+ }
1964
+ ) : null,
1965
+ showChoices ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Choices, { options: options ?? [], onPick: onChoose, ...onRequestInput ? { onSomethingElse: onRequestInput } : {}, disabled: busy }) : null,
1966
+ showToolActivity ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null,
1967
+ waiting ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Thinking, { delayed: true }) : null
1866
1968
  ] })
1867
1969
  ] });
1868
1970
  });
@@ -1876,12 +1978,12 @@ function MessageCopyButton({ text }) {
1876
1978
  } catch {
1877
1979
  }
1878
1980
  };
1879
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: () => void copy(), className: "frankie-message-copy inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-transparent text-muted-foreground transition hover:border-border hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": copied ? "Copied" : "Copy message", title: copied ? "Copied" : "Copy message", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Check, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1981
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => void copy(), className: "frankie-message-copy inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-transparent text-muted-foreground transition hover:border-border hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": copied ? "Copied" : "Copy message", title: copied ? "Copied" : "Copy message", children: copied ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react7.Check, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react7.Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1880
1982
  }
1881
1983
  function TypingDots() {
1882
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "frankie-thinking inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [
1883
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "frankie-thinking-label", children: "Thinking" }),
1884
- [0, 1, 2].map((index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1984
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "frankie-thinking inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [
1985
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "frankie-thinking-label", children: "Thinking" }),
1986
+ [0, 1, 2].map((index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1885
1987
  "span",
1886
1988
  {
1887
1989
  className: cn("size-1.5 animate-pulse rounded-full bg-muted-foreground"),
@@ -1892,15 +1994,15 @@ function TypingDots() {
1892
1994
  ] });
1893
1995
  }
1894
1996
  function Thinking({ delayed = false }) {
1895
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "frankie-skeleton" + (delayed ? " is-delayed" : ""), role: "status", "aria-label": "Thinking", children: [
1896
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "frankie-skeleton-line", style: { width: "62%" } }),
1897
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "frankie-skeleton-line", style: { width: "92%" } }),
1898
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "frankie-skeleton-line", style: { width: "48%" } })
1997
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-skeleton" + (delayed ? " is-delayed" : ""), role: "status", "aria-label": "Thinking", children: [
1998
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "frankie-skeleton-line", style: { width: "62%" } }),
1999
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "frankie-skeleton-line", style: { width: "92%" } }),
2000
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "frankie-skeleton-line", style: { width: "48%" } })
1899
2001
  ] });
1900
2002
  }
1901
2003
 
1902
2004
  // src/components/chat/ChatPanel.tsx
1903
- var import_jsx_runtime15 = require("react/jsx-runtime");
2005
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1904
2006
  function ChatPanel({
1905
2007
  className,
1906
2008
  header,
@@ -1915,7 +2017,7 @@ function ChatPanel({
1915
2017
  }) {
1916
2018
  const { config, configError, loading } = useFrankie();
1917
2019
  const theme = useFrankieTheme();
1918
- const { messages, busy, restoring, error, send, stop, reset } = useFrankieChat();
2020
+ const { messages, busy, restoring, error, send, answerAction, stop, reset } = useFrankieChat();
1919
2021
  const scrollRef = (0, import_react10.useRef)(null);
1920
2022
  const atBottomRef = (0, import_react10.useRef)(true);
1921
2023
  const features = config?.features;
@@ -1944,7 +2046,7 @@ function ChatPanel({
1944
2046
  }, [messages]);
1945
2047
  const name = config?.branding.name ?? "Assistant";
1946
2048
  const mode = useResolvedMode(theme?.mode);
1947
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2049
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1948
2050
  Card,
1949
2051
  {
1950
2052
  className: cn(
@@ -1957,22 +2059,22 @@ function ChatPanel({
1957
2059
  style: themeToCssVars(theme),
1958
2060
  "data-frankie-mode": mode,
1959
2061
  children: [
1960
- header === false ? null : header !== void 0 ? header : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(CardHeader, { children: [
1961
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
1962
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "min-w-0 flex-1", children: [
1963
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardTitle, { children: name }),
1964
- config?.branding.tagline ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardDescription, { children: config.branding.tagline }) : null
2062
+ header === false ? null : header !== void 0 ? header : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(CardHeader, { children: [
2063
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "min-w-0 flex-1", children: [
2065
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardTitle, { children: name }),
2066
+ config?.branding.tagline ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardDescription, { children: config.branding.tagline }) : null
1965
2067
  ] }),
1966
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react7.RotateCcw, {}) }),
1967
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react7.X, {}) }) : null
2068
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react8.RotateCcw, {}) }),
2069
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react8.X, {}) }) : null
1968
2070
  ] }),
1969
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AgentContext, {}),
1970
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardContent, { className: "frankie-conversation-content", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ScrollArea, { ref: scrollRef, className: "frankie-transcript flex h-full flex-col gap-4 p-4", "aria-live": "polite", children: configError ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "frankie-config-error", role: "alert", children: [
1971
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: "Frankie couldn\u2019t start" }),
1972
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { children: configError }),
1973
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
1974
- ] }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChatEmptyState, {}) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "frankie-message-list flex flex-col gap-4", children: messages.map(
1975
- (message, index) => renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2071
+ config?.agentContext === false ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AgentContext, {}),
2072
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardContent, { className: "frankie-conversation-content", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ScrollArea, { ref: scrollRef, className: "frankie-transcript flex h-full flex-col gap-4 p-4", "aria-live": "polite", children: configError ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "frankie-config-error", role: "alert", children: [
2073
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "Frankie couldn\u2019t start" }),
2074
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: configError }),
2075
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
2076
+ ] }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChatEmptyState, {}) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "frankie-message-list flex flex-col gap-4", children: messages.map(
2077
+ (message, index) => renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1976
2078
  MessageBubble,
1977
2079
  {
1978
2080
  message,
@@ -1983,14 +2085,15 @@ function ChatPanel({
1983
2085
  onChoose: send,
1984
2086
  onRequestInput: focusComposer,
1985
2087
  active: index === messages.length - 1,
1986
- busy
2088
+ busy,
2089
+ onAction: (toolUseId, approved) => void answerAction(toolUseId, approved)
1987
2090
  },
1988
2091
  message.id
1989
2092
  )
1990
2093
  ) }) }) }),
1991
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(CardFooter, { className: "frankie-composer-footer flex flex-col gap-2", children: [
1992
- error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
1993
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2094
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(CardFooter, { className: "frankie-composer-footer flex flex-col gap-2", children: [
2095
+ error ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
2096
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1994
2097
  Composer,
1995
2098
  {
1996
2099
  onSend: send,
@@ -2012,7 +2115,7 @@ function ChatPanel({
2012
2115
  }
2013
2116
 
2014
2117
  // src/components/chat/FrankieWidget.tsx
2015
- var import_jsx_runtime16 = require("react/jsx-runtime");
2118
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2016
2119
  function FrankieWidget({
2017
2120
  position = "bottom-right",
2018
2121
  offset = 24,
@@ -2098,7 +2201,7 @@ function FrankieWidget({
2098
2201
  const label = config?.branding.launcherLabel ?? "Need a hand?";
2099
2202
  const mode = useResolvedMode(theme?.mode);
2100
2203
  const side = position === "bottom-right" ? { right: offset } : { left: offset };
2101
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2204
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2102
2205
  "div",
2103
2206
  {
2104
2207
  ref: rootRef,
@@ -2106,9 +2209,9 @@ function FrankieWidget({
2106
2209
  style: { ...themeToCssVars(theme), position: "fixed", bottom: lift ? lift + Math.min(offset, 12) : offset, ...side, zIndex, pointerEvents: "none", ["--frankie-lift"]: `${lift}px`, ...stylesReady && themeReady ? null : { opacity: 0 } },
2107
2210
  "data-frankie-mode": mode,
2108
2211
  "data-frankie-styles": stylesReady ? "ready" : "pending",
2109
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
2110
- open ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
2111
- launcher || renderLauncher ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2212
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
2213
+ open ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
2214
+ launcher || renderLauncher ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2112
2215
  Button,
2113
2216
  {
2114
2217
  size: "icon",
@@ -2117,7 +2220,7 @@ function FrankieWidget({
2117
2220
  "aria-expanded": open,
2118
2221
  "aria-label": open ? "Close the assistant" : label,
2119
2222
  title: label,
2120
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react8.X, { className: "size-5" }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react8.MessageCircle, { className: "size-5" })
2223
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react9.X, { className: "size-5" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react9.MessageCircle, { className: "size-5" })
2121
2224
  }
2122
2225
  ) }) : null
2123
2226
  ] })
@@ -2127,14 +2230,14 @@ function FrankieWidget({
2127
2230
 
2128
2231
  // src/components/chat/FrankieInline.tsx
2129
2232
  var import_react12 = require("react");
2130
- var import_jsx_runtime17 = require("react/jsx-runtime");
2233
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2131
2234
  function FrankieInline({ className, style, ...panelProps }) {
2132
2235
  const { injectStyles, themeReady } = useFrankie();
2133
2236
  const theme = useFrankieTheme();
2134
2237
  const mode = useResolvedMode(theme?.mode);
2135
2238
  const rootRef = (0, import_react12.useRef)(null);
2136
2239
  const stylesReady = useStylesReady(rootRef, void 0, injectStyles);
2137
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2240
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2138
2241
  "div",
2139
2242
  {
2140
2243
  ref: rootRef,
@@ -2142,14 +2245,14 @@ function FrankieInline({ className, style, ...panelProps }) {
2142
2245
  style: { ...themeToCssVars(theme), display: "flex", height: "100%", width: "100%", ...style, ...stylesReady && themeReady ? null : { opacity: 0 } },
2143
2246
  "data-frankie-mode": mode,
2144
2247
  "data-frankie-styles": stylesReady ? "ready" : "pending",
2145
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ChatPanel, { ...panelProps, fill: true })
2248
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChatPanel, { ...panelProps, fill: true })
2146
2249
  }
2147
2250
  );
2148
2251
  }
2149
2252
 
2150
2253
  // src/components/chat/FrankieChatPage.tsx
2151
2254
  var import_react14 = require("react");
2152
- var import_lucide_react9 = require("lucide-react");
2255
+ var import_lucide_react10 = require("lucide-react");
2153
2256
 
2154
2257
  // src/lib/viewport-fill.ts
2155
2258
  var import_react13 = require("react");
@@ -2191,7 +2294,7 @@ function useViewportFill(ref, enabled) {
2191
2294
  }
2192
2295
 
2193
2296
  // src/components/chat/FrankieChatPage.tsx
2194
- var import_jsx_runtime18 = require("react/jsx-runtime");
2297
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2195
2298
  function groupByDate(items) {
2196
2299
  const now = /* @__PURE__ */ new Date();
2197
2300
  const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
@@ -2284,70 +2387,70 @@ function PageChrome({ showHistory, navigation, currentId, onSelect, onNew, histo
2284
2387
  close();
2285
2388
  }
2286
2389
  };
2287
- const history = /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
2288
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "frankie-history-heading", children: [
2289
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("strong", { children: "Conversations" }),
2290
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.X, { size: 18 }) })
2390
+ const history = /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
2391
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "frankie-history-heading", children: [
2392
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("strong", { children: "Conversations" }),
2393
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.X, { size: 18 }) })
2291
2394
  ] }),
2292
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
2395
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
2293
2396
  onNew();
2294
2397
  close();
2295
2398
  }, children: [
2296
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.Plus, { size: 17 }),
2399
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.Plus, { size: 17 }),
2297
2400
  "New chat"
2298
2401
  ] }),
2299
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "frankie-history-search", children: [
2300
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Search conversations" }),
2301
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
2402
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "frankie-history-search", children: [
2403
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Search conversations" }),
2404
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
2302
2405
  ] }),
2303
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: groupByDate(conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase()))).map((group) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "frankie-history-group", children: [
2304
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "frankie-history-group-label", children: group.label }),
2305
- group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
2306
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: item.title }),
2307
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("small", { children: new Date(item.updatedAt).toLocaleDateString() })
2406
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: groupByDate(conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase()))).map((group) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "frankie-history-group", children: [
2407
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "frankie-history-group-label", children: group.label }),
2408
+ group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
2409
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: item.title }),
2410
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("small", { children: new Date(item.updatedAt).toLocaleDateString() })
2308
2411
  ] }, item.id))
2309
2412
  ] }, group.label)) }),
2310
- historyLoading && !conversations.length ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { role: "status", children: [
2413
+ historyLoading && !conversations.length ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { role: "status", children: [
2311
2414
  historyError,
2312
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
2313
- ] }) : !conversations.length && !historyLoading ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
2314
- navigation ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "frankie-host-navigation", children: navigation }) : null
2415
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
2416
+ ] }) : !conversations.length && !historyLoading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
2417
+ navigation ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "frankie-host-navigation", children: navigation }) : null
2315
2418
  ] });
2316
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "frankie-page-shell" + (mode === "dark" ? " dark" : ""), style: { ...themeToCssVars(theme), ...themeReady ? null : { opacity: 0 } }, children: [
2317
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("aside", { className: "frankie-history-desktop" + (collapsed ? " frankie-history-collapsed" : ""), children: [
2318
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "frankie-history-toggle", "aria-label": collapsed ? "Expand conversations" : "Collapse conversations", "aria-expanded": !collapsed, onClick: () => setCollapsed((value) => !value), children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ChevronsRight, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ChevronsLeft, { size: 16 }) }),
2419
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "frankie-page-shell" + (mode === "dark" ? " dark" : ""), style: { ...themeToCssVars(theme), ...themeReady ? null : { opacity: 0 } }, children: [
2420
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("aside", { className: "frankie-history-desktop" + (collapsed ? " frankie-history-collapsed" : ""), children: [
2421
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "frankie-history-toggle", "aria-label": collapsed ? "Expand conversations" : "Collapse conversations", "aria-expanded": !collapsed, onClick: () => setCollapsed((value) => !value), children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.ChevronsRight, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.ChevronsLeft, { size: 16 }) }),
2319
2422
  collapsed ? null : history
2320
2423
  ] }) : null,
2321
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "frankie-page-main", children: [
2322
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("header", { className: "frankie-page-header", children: [
2323
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
2324
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "frankie-mobile-only", ref: menu, "aria-label": "Open conversations", "aria-haspopup": "dialog", "aria-expanded": drawerOpen, onClick: () => setDrawerOpen(true), children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.Menu, { size: 20 }) }) : null,
2325
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("strong", { className: "frankie-thread-title", children: conversations.find((item) => item.id === currentId)?.title ?? messages.find((message) => message.role === "user")?.text ?? "New chat" })
2424
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "frankie-page-main", children: [
2425
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("header", { className: "frankie-page-header", children: [
2426
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
2427
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "frankie-mobile-only", ref: menu, "aria-label": "Open conversations", "aria-haspopup": "dialog", "aria-expanded": drawerOpen, onClick: () => setDrawerOpen(true), children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.Menu, { size: 20 }) }) : null,
2428
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("strong", { className: "frankie-thread-title", children: conversations.find((item) => item.id === currentId)?.title ?? messages.find((message) => message.role === "user")?.text ?? "New chat" })
2326
2429
  ] }),
2327
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
2328
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
2329
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.Plus, { size: 16 }),
2330
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "New chat" })
2430
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
2431
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
2432
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.Plus, { size: 16 }),
2433
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "New chat" })
2331
2434
  ] }),
2332
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("details", { className: "frankie-chat-settings", children: [
2333
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.Settings, { size: 19 }) }),
2334
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
2335
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("strong", { children: "Chat settings" }),
2336
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { children: "History syncs automatically for signed-in users." }),
2337
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
2338
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.History, { size: 16 }),
2435
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("details", { className: "frankie-chat-settings", children: [
2436
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.Settings, { size: 19 }) }),
2437
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
2438
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("strong", { children: "Chat settings" }),
2439
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { children: "History syncs automatically for signed-in users." }),
2440
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
2441
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react10.History, { size: 16 }),
2339
2442
  "Refresh history"
2340
2443
  ] }),
2341
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("small", { children: "Skills are checked at the start of each message." })
2444
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("small", { children: "Skills are checked at the start of each message." })
2342
2445
  ] })
2343
2446
  ] })
2344
2447
  ] })
2345
2448
  ] }),
2346
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FrankieInline, { ...panel, header: panel.header ?? false, placeholder: panel.placeholder ?? `Ask anything about your ${config?.branding.name ?? "Frankie"} workspace\u2026`, emptyState: panel.emptyState }) })
2449
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FrankieInline, { ...panel, header: panel.header ?? false, placeholder: panel.placeholder ?? `Ask anything about your ${config?.branding.name ?? "Frankie"} workspace\u2026`, emptyState: panel.emptyState }) })
2347
2450
  ] }),
2348
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
2451
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
2349
2452
  if (event.target === event.currentTarget) close();
2350
- }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("aside", { children: history }) }) : null
2453
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("aside", { children: history }) }) : null
2351
2454
  ] });
2352
2455
  }
2353
2456
  function FrankieChatPage({ className, style, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus, showHistory = true, navigation, fillViewport = true, ...provider }) {
@@ -2357,18 +2460,18 @@ function FrankieChatPage({ className, style, header, footer, emptyState, renderM
2357
2460
  const pageRef = (0, import_react14.useRef)(null);
2358
2461
  const stylesReady = useStylesReady(pageRef, void 0, provider.injectStyles);
2359
2462
  const fill = useViewportFill(pageRef, fillViewport);
2360
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { ref: pageRef, className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: fill > 360 ? `${fill}px` : "min(36rem, 100dvh)", width: "100%", ...style, ...stylesReady ? null : { opacity: 0 } }, "data-frankie-styles": stylesReady ? "ready" : "pending", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, history, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
2463
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { ref: pageRef, className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: fill > 360 ? `${fill}px` : "min(36rem, 100dvh)", width: "100%", ...style, ...stylesReady ? null : { opacity: 0 } }, "data-frankie-styles": stylesReady ? "ready" : "pending", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, history, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
2361
2464
  }
2362
2465
 
2363
2466
  // src/components/chat/SuggestedPrompts.tsx
2364
- var import_jsx_runtime19 = require("react/jsx-runtime");
2467
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2365
2468
  function SuggestedPrompts({
2366
2469
  prompts,
2367
2470
  onPick,
2368
2471
  disabled
2369
2472
  }) {
2370
2473
  if (prompts.length === 0) return null;
2371
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2474
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2372
2475
  Button,
2373
2476
  {
2374
2477
  type: "button",
@@ -2383,12 +2486,13 @@ function SuggestedPrompts({
2383
2486
  }
2384
2487
 
2385
2488
  // src/components/ui/separator.tsx
2386
- var import_jsx_runtime20 = require("react/jsx-runtime");
2489
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2387
2490
  function Separator({ className }) {
2388
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
2491
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
2389
2492
  }
2390
2493
  // Annotate the CommonJS export names for ESM import in node:
2391
2494
  0 && (module.exports = {
2495
+ ActionConfirm,
2392
2496
  Avatar,
2393
2497
  Badge,
2394
2498
  Button,