@frankieai/react 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -601,7 +601,7 @@ function useFrankieTheme() {
601
601
  }
602
602
 
603
603
  // src/components/chat/FrankieWidget.tsx
604
- var import_lucide_react5 = require("lucide-react");
604
+ var import_lucide_react6 = require("lucide-react");
605
605
  var import_react9 = require("react");
606
606
 
607
607
  // src/lib/theme.ts
@@ -662,7 +662,7 @@ function Button({ className, variant, size, asChild = false, ...props }) {
662
662
  }
663
663
 
664
664
  // src/components/chat/ChatPanel.tsx
665
- var import_lucide_react4 = require("lucide-react");
665
+ var import_lucide_react5 = require("lucide-react");
666
666
  var import_react8 = require("react");
667
667
 
668
668
  // src/components/ui/avatar.tsx
@@ -721,16 +721,51 @@ var ScrollArea = (0, import_react3.forwardRef)(
721
721
  }
722
722
  );
723
723
 
724
- // src/components/chat/Composer.tsx
724
+ // src/components/chat/AgentContext.tsx
725
725
  var import_lucide_react = require("lucide-react");
726
+ var import_jsx_runtime6 = require("react/jsx-runtime");
727
+ function AgentContext() {
728
+ const { loading, configError } = useFrankie();
729
+ const { loadedSkills, busy, restoring, error } = useFrankieChat();
730
+ const status = configError || error ? "Unavailable" : loading || restoring ? "Connecting" : busy && loadedSkills === null ? "Checking" : loadedSkills?.length ? "Active" : loadedSkills ? "Tools only" : "Ready";
731
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "frankie-agent-context-wrap", children: [
732
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("details", { className: "frankie-agent-context", children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("summary", { "aria-label": "Agent context", children: [
734
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Sparkles, { size: 17, "aria-hidden": "true" }),
735
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Agent context" }),
736
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "frankie-context-count", children: loadedSkills === null ? "Not checked" : `${loadedSkills.length} ${loadedSkills.length === 1 ? "skill" : "skills"}` }),
737
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "frankie-context-status", "data-active": status === "Active", children: [
738
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", { "aria-hidden": "true" }),
739
+ status
740
+ ] }),
741
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ArrowUpRight, { size: 15, "aria-hidden": "true" })
742
+ ] }),
743
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "frankie-context-detail", children: [
744
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: loadedSkills === null ? "Skills are checked when you send a message" : loadedSkills.length ? `${loadedSkills.length} ${loadedSkills.length === 1 ? "skill" : "skills"} loaded` : "No skills loaded for this turn" }),
745
+ loadedSkills?.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { children: loadedSkills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: skill.name }),
747
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("small", { children: [
748
+ "v",
749
+ skill.revision
750
+ ] })
751
+ ] }, skill.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Frankie can use the tools approved for this workspace. Drafts and skills without available tools are not loaded." }),
752
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Published skills and updates are checked on every message. Only approved, available tools can run." })
753
+ ] })
754
+ ] }),
755
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "frankie-sr-only", role: "status", children: loadedSkills === null ? status : `${loadedSkills.length} ${loadedSkills.length === 1 ? "skill" : "skills"} loaded. ${status}.` })
756
+ ] });
757
+ }
758
+
759
+ // src/components/chat/Composer.tsx
760
+ var import_lucide_react2 = require("lucide-react");
726
761
  var import_react5 = require("react");
727
762
 
728
763
  // src/components/ui/textarea.tsx
729
764
  var import_react4 = require("react");
730
- var import_jsx_runtime6 = require("react/jsx-runtime");
765
+ var import_jsx_runtime7 = require("react/jsx-runtime");
731
766
  var Textarea = (0, import_react4.forwardRef)(
732
767
  function Textarea2({ className, ...props }, ref) {
733
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
768
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
734
769
  "textarea",
735
770
  {
736
771
  ref,
@@ -745,7 +780,7 @@ var Textarea = (0, import_react4.forwardRef)(
745
780
  );
746
781
 
747
782
  // src/components/chat/Composer.tsx
748
- var import_jsx_runtime7 = require("react/jsx-runtime");
783
+ var import_jsx_runtime8 = require("react/jsx-runtime");
749
784
  var MAX_ROWS_PX = 140;
750
785
  function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, attachments, modelPicker }) {
751
786
  const [value, setValue] = (0, import_react5.useState)("");
@@ -807,46 +842,46 @@ function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, atta
807
842
  });
808
843
  }, [busy, disabled, files, modelPicker?.value, onSend, value]);
809
844
  const onKeyDown = (event) => {
810
- if (event.key === "Enter" && !event.shiftKey) {
845
+ if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
811
846
  event.preventDefault();
812
847
  submit();
813
848
  }
814
849
  };
815
850
  const nothingToSend = value.trim().length === 0 && files.length === 0;
816
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
851
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
817
852
  "form",
818
853
  {
819
- className: "flex flex-col gap-2",
854
+ className: "frankie-composer flex flex-col gap-2",
820
855
  onSubmit: (event) => {
821
856
  event.preventDefault();
822
857
  submit();
823
858
  },
824
859
  children: [
825
- files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-2", children: files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
860
+ files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-wrap gap-2", children: files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
826
861
  "span",
827
862
  {
828
863
  className: "inline-flex max-w-[14rem] items-center gap-1.5 rounded-[var(--frankie-radius)] border border-border bg-muted px-2 py-1 text-xs",
829
864
  children: [
830
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
831
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: file.name }),
832
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
865
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
866
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate", children: file.name }),
867
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
833
868
  "button",
834
869
  {
835
870
  type: "button",
836
871
  onClick: () => removeFile(file.id),
837
872
  "aria-label": `Remove ${file.name}`,
838
873
  className: "frankie-focus shrink-0 opacity-60 hover:opacity-100",
839
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.X, { className: "size-3" })
874
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.X, { className: "size-3" })
840
875
  }
841
876
  )
842
877
  ]
843
878
  },
844
879
  file.id
845
880
  )) }) : null,
846
- fileError ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs text-red-600 dark:text-red-400", children: fileError }) : null,
847
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-end gap-2", children: [
848
- canAttach ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
849
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
881
+ fileError ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-xs text-red-600 dark:text-red-400", children: fileError }) : null,
882
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "frankie-composer-controls flex items-end gap-2", children: [
883
+ canAttach ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
884
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
850
885
  "input",
851
886
  {
852
887
  ref: fileInputRef,
@@ -860,7 +895,7 @@ function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, atta
860
895
  }
861
896
  }
862
897
  ),
863
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
898
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
864
899
  Button,
865
900
  {
866
901
  type: "button",
@@ -870,11 +905,11 @@ function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, atta
870
905
  onClick: () => fileInputRef.current?.click(),
871
906
  "aria-label": "Attach files",
872
907
  title: "Attach files",
873
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.Paperclip, {})
908
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Plus, {})
874
909
  }
875
910
  )
876
911
  ] }) : null,
877
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
912
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
878
913
  Textarea,
879
914
  {
880
915
  ref: textareaRef,
@@ -888,7 +923,7 @@ function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, atta
888
923
  "aria-label": "Message"
889
924
  }
890
925
  ),
891
- models.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
926
+ models.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
892
927
  "select",
893
928
  {
894
929
  value: modelPicker?.value ?? models[0]?.id,
@@ -896,10 +931,10 @@ function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, atta
896
931
  disabled,
897
932
  "aria-label": "Model",
898
933
  className: "frankie-focus h-9 max-w-[8rem] rounded-[var(--frankie-radius)] border border-border bg-background px-2 text-sm",
899
- children: models.map((model) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: model.id, children: model.label }, model.id))
934
+ children: models.map((model) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: model.id, children: model.label }, model.id))
900
935
  }
901
936
  ) : null,
902
- busy ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { type: "button", size: "icon", variant: "outline", onClick: onStop, "aria-label": "Stop", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.Square, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { type: "submit", size: "icon", disabled: disabled || nothingToSend, "aria-label": "Send", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.ArrowUp, {}) })
937
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { type: "button", size: "icon", variant: "outline", onClick: onStop, "aria-label": "Stop", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Square, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { type: "submit", size: "icon", disabled: disabled || nothingToSend, "aria-label": "Send", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ArrowUp, {}) })
903
938
  ] })
904
939
  ]
905
940
  }
@@ -924,14 +959,14 @@ function readAsBase64(file) {
924
959
  }
925
960
 
926
961
  // src/components/chat/MessageBubble.tsx
927
- var import_lucide_react3 = require("lucide-react");
962
+ var import_lucide_react4 = require("lucide-react");
928
963
  var import_react7 = require("react");
929
964
 
930
965
  // src/components/chat/Markdown.tsx
931
966
  var import_react6 = require("react");
932
- var import_jsx_runtime8 = require("react/jsx-runtime");
967
+ var import_jsx_runtime9 = require("react/jsx-runtime");
933
968
  function Markdown({ text, className }) {
934
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn("frankie-prose", className), children: renderBlocks(text) });
969
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: cn("frankie-prose", className), children: renderBlocks(text) });
935
970
  }
936
971
  function renderBlocks(text) {
937
972
  const lines = text.split("\n");
@@ -941,13 +976,13 @@ function renderBlocks(text) {
941
976
  let code = null;
942
977
  const flushParagraph = () => {
943
978
  if (paragraph.length === 0) return;
944
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
979
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: renderInline(paragraph.join(" ")) }, `p${blocks.length}`));
945
980
  paragraph = [];
946
981
  };
947
982
  const flushList = () => {
948
983
  if (!list) return;
949
- const items = list.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { children: renderInline(item) }, index));
950
- blocks.push(list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { children: items }, `l${blocks.length}`));
984
+ const items = list.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { children: renderInline(item) }, index));
985
+ blocks.push(list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ol", { children: items }, `l${blocks.length}`) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { children: items }, `l${blocks.length}`));
951
986
  list = null;
952
987
  };
953
988
  for (const line of lines) {
@@ -955,7 +990,7 @@ function renderBlocks(text) {
955
990
  if (fence) {
956
991
  if (code) {
957
992
  blocks.push(
958
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
993
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
959
994
  );
960
995
  code = null;
961
996
  } else {
@@ -990,7 +1025,7 @@ function renderBlocks(text) {
990
1025
  if (heading) {
991
1026
  flushParagraph();
992
1027
  flushList();
993
- blocks.push(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "font-semibold", children: renderInline(heading[1] ?? "") }, `h${blocks.length}`));
1028
+ blocks.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "font-semibold", children: renderInline(heading[1] ?? "") }, `h${blocks.length}`));
994
1029
  continue;
995
1030
  }
996
1031
  flushList();
@@ -998,7 +1033,7 @@ function renderBlocks(text) {
998
1033
  }
999
1034
  if (code) {
1000
1035
  blocks.push(
1001
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1036
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("code", { children: code.lines.join("\n") }) }, `c${blocks.length}`)
1002
1037
  );
1003
1038
  }
1004
1039
  flushParagraph();
@@ -1013,28 +1048,28 @@ function renderInline(text) {
1013
1048
  const token = match[0];
1014
1049
  const start = match.index;
1015
1050
  if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
1016
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react6.Fragment, { children: renderToken(token) }, start));
1051
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react6.Fragment, { children: renderToken(token) }, start));
1017
1052
  lastIndex = start + token.length;
1018
1053
  }
1019
1054
  if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
1020
1055
  return nodes;
1021
1056
  }
1022
1057
  function renderToken(token) {
1023
- if (token.startsWith("**")) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: token.slice(2, -2) });
1024
- if (token.startsWith("`")) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { children: token.slice(1, -1) });
1058
+ if (token.startsWith("**")) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: token.slice(2, -2) });
1059
+ if (token.startsWith("`")) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("code", { children: token.slice(1, -1) });
1025
1060
  const link = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(token);
1026
1061
  const href = link ? link[2] ?? "" : token;
1027
1062
  const label = link ? link[1] ?? "" : token;
1028
1063
  if (!/^(https?:\/\/|\/)/.test(href)) return token;
1029
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1064
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer nofollow", children: label });
1030
1065
  }
1031
1066
 
1032
1067
  // src/components/chat/ToolActivityList.tsx
1033
- var import_lucide_react2 = require("lucide-react");
1068
+ var import_lucide_react3 = require("lucide-react");
1034
1069
 
1035
1070
  // src/components/ui/badge.tsx
1036
1071
  var import_class_variance_authority2 = require("class-variance-authority");
1037
- var import_jsx_runtime9 = require("react/jsx-runtime");
1072
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1038
1073
  var badgeVariants = (0, import_class_variance_authority2.cva)(
1039
1074
  "inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[0.6875rem] font-medium",
1040
1075
  {
@@ -1054,44 +1089,44 @@ function Badge({
1054
1089
  variant,
1055
1090
  ...props
1056
1091
  }) {
1057
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: cn(badgeVariants({ variant }), className), ...props });
1092
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn(badgeVariants({ variant }), className), ...props });
1058
1093
  }
1059
1094
 
1060
1095
  // src/components/chat/ToolActivityList.tsx
1061
- var import_jsx_runtime10 = require("react/jsx-runtime");
1096
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1062
1097
  function ToolActivityList({ tools, renderTool }) {
1063
1098
  if (tools.length === 0) return null;
1064
1099
  const running = tools.some((tool) => tool.status === "running");
1065
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1066
- /* @__PURE__ */ (0, import_jsx_runtime10.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: [
1067
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react2.ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1068
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: running ? "Working" : "Activity" }),
1069
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-[11px]", children: [
1100
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("details", { className: "frankie-tool-activity mt-2", open: running, children: [
1101
+ /* @__PURE__ */ (0, import_jsx_runtime11.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: [
1102
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ChevronDown, { className: "frankie-tool-chevron size-3.5 transition-transform", "aria-hidden": "true" }),
1103
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: running ? "Working" : "Activity" }),
1104
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-[11px]", children: [
1070
1105
  "\xB7 ",
1071
1106
  tools.length,
1072
1107
  " tool call",
1073
1108
  tools.length === 1 ? "" : "s"
1074
1109
  ] })
1075
1110
  ] }),
1076
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolActivityRow, { tool }) }, tool.id)) })
1111
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "mt-1 flex flex-col gap-1 border-l border-border pl-2", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("li", { children: renderTool ? renderTool(tool) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ToolActivityRow, { tool }) }, tool.id)) })
1077
1112
  ] });
1078
1113
  }
1079
1114
  function ToolActivityRow({ tool }) {
1080
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1081
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ToolIcon, { status: tool.status }),
1082
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate", children: tool.label })
1115
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Badge, { variant: badgeVariant(tool.status), title: tool.detail ?? tool.name, children: [
1116
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ToolIcon, { status: tool.status }),
1117
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "truncate", children: tool.label })
1083
1118
  ] });
1084
1119
  }
1085
1120
  function ToolIcon({ status }) {
1086
1121
  switch (status) {
1087
1122
  case "running":
1088
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react2.Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1123
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Loader2, { className: "size-3 animate-spin", "aria-hidden": "true" });
1089
1124
  case "done":
1090
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react2.Check, { className: "size-3", "aria-hidden": "true" });
1125
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Check, { className: "size-3", "aria-hidden": "true" });
1091
1126
  case "denied":
1092
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react2.ShieldAlert, { className: "size-3", "aria-hidden": "true" });
1127
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ShieldAlert, { className: "size-3", "aria-hidden": "true" });
1093
1128
  default:
1094
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react2.X, { className: "size-3", "aria-hidden": "true" });
1129
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.X, { className: "size-3", "aria-hidden": "true" });
1095
1130
  }
1096
1131
  }
1097
1132
  function badgeVariant(status) {
@@ -1102,7 +1137,7 @@ function badgeVariant(status) {
1102
1137
  }
1103
1138
 
1104
1139
  // src/components/chat/MessageBubble.tsx
1105
- var import_jsx_runtime11 = require("react/jsx-runtime");
1140
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1106
1141
  function MessageBubble({
1107
1142
  message,
1108
1143
  assistantName,
@@ -1111,33 +1146,33 @@ function MessageBubble({
1111
1146
  renderTool
1112
1147
  }) {
1113
1148
  if (message.role === "user") {
1114
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col items-end gap-1", children: [
1115
- message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1149
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "frankie-user-message flex flex-col items-end gap-1", children: [
1150
+ message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex max-w-[85%] flex-wrap justify-end gap-1", children: message.attachments.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1116
1151
  "span",
1117
1152
  {
1118
1153
  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",
1119
1154
  children: [
1120
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
1121
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "truncate", children: file.name })
1155
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.Paperclip, { className: "size-3 shrink-0 opacity-70" }),
1156
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "truncate", children: file.name })
1122
1157
  ]
1123
1158
  },
1124
1159
  `${file.name}-${index}`
1125
1160
  )) }) : null,
1126
- message.text ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1127
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1128
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageCopyButton, { text: message.text })
1161
+ message.text ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex max-w-[85%] items-end gap-1", children: [
1162
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "frankie-user-bubble rounded-[var(--frankie-radius)] bg-primary px-3 py-2 text-sm text-primary-foreground", children: message.text }),
1163
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MessageCopyButton, { text: message.text })
1129
1164
  ] }) : null
1130
1165
  ] });
1131
1166
  }
1132
1167
  const empty = message.text.length === 0 && message.tools.length === 0;
1133
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-2", children: [
1134
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1135
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1136
- message.text ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageCopyButton, { text: message.text }) : null
1168
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "frankie-assistant-message flex gap-2", children: [
1169
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "frankie-assistant-actions mt-0.5 flex shrink-0 flex-col items-center gap-1", children: [
1170
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Avatar, { ...avatarUrl ? { src: avatarUrl } : {}, name: assistantName }),
1171
+ message.text ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MessageCopyButton, { text: message.text }) : null
1137
1172
  ] }),
1138
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "min-w-0 max-w-[85%]", children: [
1139
- message.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime11.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 }) : empty && message.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TypingDots, {}) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Markdown, { text: message.text, className: "text-sm" }),
1140
- showToolActivity ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null
1173
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "frankie-assistant-content min-w-0 max-w-[85%]", children: [
1174
+ message.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime12.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 }) : empty && message.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TypingDots, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Markdown, { text: message.text, className: "text-sm" }),
1175
+ showToolActivity ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ToolActivityList, { tools: message.tools, ...renderTool ? { renderTool } : {} }) : null
1141
1176
  ] })
1142
1177
  ] });
1143
1178
  }
@@ -1151,28 +1186,31 @@ function MessageCopyButton({ text }) {
1151
1186
  } catch {
1152
1187
  }
1153
1188
  };
1154
- return /* @__PURE__ */ (0, import_jsx_runtime11.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_runtime11.jsx)(import_lucide_react3.Check, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1189
+ return /* @__PURE__ */ (0, import_jsx_runtime12.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_runtime12.jsx)(import_lucide_react4.Check, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.Copy, { className: "size-3.5", "aria-hidden": "true" }) });
1155
1190
  }
1156
1191
  function TypingDots() {
1157
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [0, 1, 2].map((index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1158
- "span",
1159
- {
1160
- className: cn("size-1.5 animate-pulse rounded-full bg-muted-foreground"),
1161
- style: { animationDelay: `${index * 150}ms` }
1162
- },
1163
- index
1164
- )) });
1192
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "frankie-thinking inline-flex items-center gap-1 py-2", role: "status", "aria-label": "Thinking", children: [
1193
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "frankie-thinking-label", children: "Thinking" }),
1194
+ [0, 1, 2].map((index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1195
+ "span",
1196
+ {
1197
+ className: cn("size-1.5 animate-pulse rounded-full bg-muted-foreground"),
1198
+ style: { animationDelay: `${index * 150}ms` }
1199
+ },
1200
+ index
1201
+ ))
1202
+ ] });
1165
1203
  }
1166
1204
 
1167
1205
  // src/components/chat/SuggestedPrompts.tsx
1168
- var import_jsx_runtime12 = require("react/jsx-runtime");
1206
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1169
1207
  function SuggestedPrompts({
1170
1208
  prompts,
1171
1209
  onPick,
1172
1210
  disabled
1173
1211
  }) {
1174
1212
  if (prompts.length === 0) return null;
1175
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1213
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex flex-wrap gap-2", children: prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1176
1214
  Button,
1177
1215
  {
1178
1216
  type: "button",
@@ -1187,7 +1225,7 @@ function SuggestedPrompts({
1187
1225
  }
1188
1226
 
1189
1227
  // src/components/chat/ChatPanel.tsx
1190
- var import_jsx_runtime13 = require("react/jsx-runtime");
1228
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1191
1229
  function ChatPanel({
1192
1230
  className,
1193
1231
  header,
@@ -1202,7 +1240,7 @@ function ChatPanel({
1202
1240
  }) {
1203
1241
  const { config, configError, loading } = useFrankie();
1204
1242
  const theme = useFrankieTheme();
1205
- const { messages, busy, restoring, loadedSkills, error, send, stop, reset } = useFrankieChat();
1243
+ const { messages, busy, restoring, error, send, stop, reset } = useFrankieChat();
1206
1244
  const scrollRef = (0, import_react8.useRef)(null);
1207
1245
  const features = config?.features;
1208
1246
  const pickerModels = features?.modelPicker.enabled ? features.modelPicker.models : [];
@@ -1215,11 +1253,12 @@ function ChatPanel({
1215
1253
  }, [messages]);
1216
1254
  const name = config?.branding.name ?? "Assistant";
1217
1255
  const mode = resolveMode(theme?.mode);
1218
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1256
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1219
1257
  Card,
1220
1258
  {
1221
1259
  className: cn(
1222
- "frankie-root",
1260
+ "frankie-root frankie-chat-panel",
1261
+ fill && "frankie-chat-panel-fill",
1223
1262
  fill ? "h-full w-full rounded-none border-0 shadow-none" : "h-[32rem] w-[22rem] max-w-[calc(100vw-2rem)]",
1224
1263
  mode === "dark" && "dark",
1225
1264
  className
@@ -1227,24 +1266,25 @@ function ChatPanel({
1227
1266
  style: themeToCssVars(theme),
1228
1267
  "data-frankie-mode": mode,
1229
1268
  children: [
1230
- header === false ? null : header !== void 0 ? header : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardHeader, { children: [
1231
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
1232
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "min-w-0 flex-1", children: [
1233
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardTitle, { children: name }),
1234
- config?.branding.tagline ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardDescription, { children: config.branding.tagline }) : null
1269
+ header === false ? null : header !== void 0 ? header : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(CardHeader, { children: [
1270
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Avatar, { ...config?.branding.avatarUrl ? { src: config.branding.avatarUrl } : {}, name }),
1271
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "min-w-0 flex-1", children: [
1272
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CardTitle, { children: name }),
1273
+ config?.branding.tagline ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CardDescription, { children: config.branding.tagline }) : null
1235
1274
  ] }),
1236
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.RotateCcw, {}) }),
1237
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.X, {}) }) : null
1275
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "icon", variant: "ghost", onClick: reset, "aria-label": "Start a new conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.RotateCcw, {}) }),
1276
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { size: "icon", variant: "ghost", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.X, {}) }) : null
1238
1277
  ] }),
1239
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollArea, { ref: scrollRef, className: "flex h-full flex-col gap-4 p-4", "aria-live": "polite", children: configError ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "frankie-config-error", role: "alert", children: [
1240
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Frankie couldn\u2019t start" }),
1241
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: configError }),
1242
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
1243
- ] }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-4", children: [
1244
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm text-muted-foreground", children: config?.greeting }),
1245
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SuggestedPrompts, { prompts: config?.suggestedPrompts ?? [], onPick: send, disabled: busy })
1246
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex flex-col gap-4", children: messages.map(
1247
- (message) => renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1278
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AgentContext, {}),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CardContent, { className: "frankie-conversation-content", children: /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.jsxs)("div", { className: "frankie-config-error", role: "alert", children: [
1280
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: "Frankie couldn\u2019t start" }),
1281
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: configError }),
1282
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: "Refresh this page after checking the workspace\u2019s allowed origin and sign-in settings." })
1283
+ ] }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-muted-foreground", children: "Starting Frankie\u2026" }) : messages.length === 0 ? emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-4", children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-muted-foreground", children: config?.greeting }),
1285
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SuggestedPrompts, { prompts: config?.suggestedPrompts ?? [], onPick: send, disabled: busy })
1286
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "frankie-message-list flex flex-col gap-4", children: messages.map(
1287
+ (message) => renderMessage ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: renderMessage(message) }, message.id) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1248
1288
  MessageBubble,
1249
1289
  {
1250
1290
  message,
@@ -1256,19 +1296,9 @@ function ChatPanel({
1256
1296
  message.id
1257
1297
  )
1258
1298
  ) }) }) }),
1259
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardFooter, { className: "flex flex-col gap-2", children: [
1260
- loadedSkills !== null ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("details", { className: "frankie-loaded-skills", children: [
1261
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("summary", { role: "status", children: loadedSkills.length ? `${loadedSkills.length} ${loadedSkills.length === 1 ? "skill" : "skills"} loaded` : "No skills loaded for this turn" }),
1262
- loadedSkills.length ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("ul", { children: loadedSkills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("li", { children: [
1263
- skill.name,
1264
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("small", { children: [
1265
- "v",
1266
- skill.revision
1267
- ] })
1268
- ] }, skill.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: "Your assistant can still answer using its available tools." })
1269
- ] }) : null,
1270
- error ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
1271
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1299
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(CardFooter, { className: "frankie-composer-footer flex flex-col gap-2", children: [
1300
+ error ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "w-full text-xs text-red-600 dark:text-red-400", children: error }) : null,
1301
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1272
1302
  Composer,
1273
1303
  {
1274
1304
  onSend: send,
@@ -1289,7 +1319,7 @@ function ChatPanel({
1289
1319
  }
1290
1320
 
1291
1321
  // src/components/chat/FrankieWidget.tsx
1292
- var import_jsx_runtime14 = require("react/jsx-runtime");
1322
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1293
1323
  function FrankieWidget({
1294
1324
  position = "bottom-right",
1295
1325
  offset = 24,
@@ -1319,15 +1349,15 @@ function FrankieWidget({
1319
1349
  const label = config?.branding.launcherLabel ?? "Need a hand?";
1320
1350
  const mode = resolveMode(theme?.mode);
1321
1351
  const side = position === "bottom-right" ? { right: offset } : { left: offset };
1322
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1352
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1323
1353
  "div",
1324
1354
  {
1325
1355
  className: cn("frankie-root frankie-widget", mode === "dark" && "dark"),
1326
1356
  style: { ...themeToCssVars(theme), position: "fixed", bottom: offset, ...side, zIndex, pointerEvents: "none" },
1327
1357
  "data-frankie-mode": mode,
1328
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
1329
- open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { pointerEvents: "auto", maxHeight: "calc(100dvh - 100px)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
1330
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1358
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: cn("flex flex-col gap-3", position === "bottom-left" ? "items-start" : "items-end"), children: [
1359
+ open ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { pointerEvents: "auto", maxHeight: "calc(100dvh - 100px)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChatPanel, { ...panelProps, className: cn("frankie-widget-panel", panelProps.className), onClose: () => setOpen(false), autoFocus: true }) }) : null,
1360
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { pointerEvents: "auto" }, children: renderLauncher ? renderLauncher({ open, toggle: () => setOpen(!open), label }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1331
1361
  Button,
1332
1362
  {
1333
1363
  size: "icon",
@@ -1336,7 +1366,7 @@ function FrankieWidget({
1336
1366
  "aria-expanded": open,
1337
1367
  "aria-label": open ? "Close the assistant" : label,
1338
1368
  title: label,
1339
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.X, { className: "size-5" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.MessageCircle, { className: "size-5" })
1369
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.X, { className: "size-5" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.MessageCircle, { className: "size-5" })
1340
1370
  }
1341
1371
  ) })
1342
1372
  ] })
@@ -1345,45 +1375,45 @@ function FrankieWidget({
1345
1375
  }
1346
1376
 
1347
1377
  // src/components/chat/FrankieInline.tsx
1348
- var import_jsx_runtime15 = require("react/jsx-runtime");
1378
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1349
1379
  function FrankieInline({ className, style, ...panelProps }) {
1350
1380
  const theme = useFrankieTheme();
1351
1381
  const mode = resolveMode(theme?.mode);
1352
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1382
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1353
1383
  "div",
1354
1384
  {
1355
1385
  className: cn("frankie-root frankie-inline", mode === "dark" && "dark", className),
1356
1386
  style: { ...themeToCssVars(theme), display: "flex", height: "100%", width: "100%", ...style },
1357
1387
  "data-frankie-mode": mode,
1358
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChatPanel, { ...panelProps, fill: true })
1388
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChatPanel, { ...panelProps, fill: true })
1359
1389
  }
1360
1390
  );
1361
1391
  }
1362
1392
 
1363
1393
  // src/components/chat/FrankieChatPage.tsx
1364
1394
  var import_react10 = require("react");
1365
- var import_lucide_react6 = require("lucide-react");
1366
- var import_jsx_runtime16 = require("react/jsx-runtime");
1395
+ var import_lucide_react7 = require("lucide-react");
1396
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1367
1397
  function PageEmptyState() {
1368
1398
  const { config } = useFrankie();
1369
1399
  const { send, busy, restoring } = useFrankieChat();
1370
1400
  const name = config?.branding.name ?? "Frankie";
1371
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { className: "frankie-page-empty", "aria-label": "Start a conversation", children: [
1372
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "frankie-page-avatar", "aria-hidden": true, children: name.trim().slice(0, 1).toUpperCase() }),
1373
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
1374
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "frankie-page-kicker", children: "Your product assistant" }),
1375
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", { children: "How can I help?" }),
1376
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: config?.greeting ?? "Ask a question or choose a task to get started." })
1401
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("section", { className: "frankie-page-empty", "aria-label": "Start a conversation", children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "frankie-page-avatar", "aria-hidden": true, children: name.trim().slice(0, 1).toUpperCase() }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
1404
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "frankie-page-kicker", children: "Your product assistant" }),
1405
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h1", { children: "How can I help?" }),
1406
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { children: config?.greeting ?? "Ask a question or choose a task to get started." })
1377
1407
  ] }),
1378
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "frankie-page-prompts", children: config?.suggestedPrompts?.slice(0, 3).map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", disabled: busy || restoring, onClick: () => void send(prompt), children: [
1379
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: prompt }),
1380
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("b", { "aria-hidden": true, children: "\u2197" })
1408
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "frankie-page-prompts", children: config?.suggestedPrompts?.slice(0, 3).map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", disabled: busy || restoring, onClick: () => void send(prompt), children: [
1409
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: prompt }),
1410
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("b", { "aria-hidden": true, children: "\u2197" })
1381
1411
  ] }, prompt)) })
1382
1412
  ] });
1383
1413
  }
1384
1414
  function PageChrome({ showHistory, navigation, currentId, onSelect, onNew, ...panel }) {
1385
1415
  const { client, config } = useFrankie();
1386
- const { busy } = useFrankieChat();
1416
+ const { busy, messages } = useFrankieChat();
1387
1417
  const theme = useFrankieTheme();
1388
1418
  const [conversations, setConversations] = (0, import_react10.useState)([]);
1389
1419
  const [historyError, setHistoryError] = (0, import_react10.useState)("");
@@ -1393,7 +1423,6 @@ function PageChrome({ showHistory, navigation, currentId, onSelect, onNew, ...pa
1393
1423
  const dialog = (0, import_react10.useRef)(null);
1394
1424
  const menu = (0, import_react10.useRef)(null);
1395
1425
  const requestVersion = (0, import_react10.useRef)(0);
1396
- const name = config?.branding.name ?? "Frankie";
1397
1426
  const refresh = (0, import_react10.useCallback)(async () => {
1398
1427
  if (!showHistory || !config || config.allowAnonymous) {
1399
1428
  setHistoryError("");
@@ -1435,77 +1464,76 @@ function PageChrome({ showHistory, navigation, currentId, onSelect, onNew, ...pa
1435
1464
  close();
1436
1465
  }
1437
1466
  };
1438
- const history = /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
1439
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "frankie-history-heading", children: [
1440
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "Conversations" }),
1441
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.X, { size: 18 }) })
1467
+ const history = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
1468
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "frankie-history-heading", children: [
1469
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "Conversations" }),
1470
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "frankie-mobile-only", "aria-label": "Close conversations", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 18 }) })
1442
1471
  ] }),
1443
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
1472
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", className: "frankie-new-chat", disabled: busy, onClick: () => {
1444
1473
  onNew();
1445
1474
  close();
1446
1475
  }, children: [
1447
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.Plus, { size: 17 }),
1476
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Plus, { size: 17 }),
1448
1477
  "New chat"
1449
1478
  ] }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "frankie-history-search", children: [
1451
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Search conversations" }),
1452
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
1479
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "frankie-history-search", children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Search conversations" }),
1481
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("input", { type: "search", placeholder: "Search chats\u2026", value: query, onChange: (event) => setQuery(event.target.value) })
1453
1482
  ] }),
1454
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase())).map((item) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
1455
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: item.title }),
1456
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("small", { children: new Date(item.updatedAt).toLocaleDateString() })
1483
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("nav", { className: "frankie-history-list", "aria-label": "Conversations", children: conversations.filter((item) => item.title.toLowerCase().includes(query.toLowerCase())).map((item) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", "aria-current": item.id === currentId ? "page" : void 0, disabled: busy, onClick: () => select(item.id), children: [
1484
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: item.title }),
1485
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("small", { children: new Date(item.updatedAt).toLocaleDateString() })
1457
1486
  ] }, item.id)) }),
1458
- historyLoading ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { role: "status", children: [
1487
+ historyLoading ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { role: "status", children: "Loading history\u2026" }) : historyError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { role: "status", children: [
1459
1488
  historyError,
1460
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
1461
- ] }) : !conversations.length ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
1462
- navigation ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "frankie-host-navigation", children: navigation }) : null
1489
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick: () => void refresh(), children: "Try again" })
1490
+ ] }) : !conversations.length ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { children: config?.allowAnonymous ? "Sign in to sync conversations across devices." : "Your conversations will appear here." }) : null,
1491
+ navigation ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "frankie-host-navigation", children: navigation }) : null
1463
1492
  ] });
1464
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "frankie-page-shell" + (resolveMode(theme?.mode) === "dark" ? " dark" : ""), style: themeToCssVars(theme), children: [
1465
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("aside", { className: "frankie-history-desktop", children: history }) : null,
1466
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "frankie-page-main", children: [
1467
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "frankie-page-header", children: [
1468
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
1469
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.jsx)(import_lucide_react6.Menu, { size: 20 }) }) : null,
1470
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: name }),
1471
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "frankie-header-caption", children: "Product assistant" })
1493
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "frankie-page-shell" + (resolveMode(theme?.mode) === "dark" ? " dark" : ""), style: themeToCssVars(theme), children: [
1494
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("aside", { className: "frankie-history-desktop", children: history }) : null,
1495
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "frankie-page-main", children: [
1496
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("header", { className: "frankie-page-header", children: [
1497
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
1498
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime17.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_runtime17.jsx)(import_lucide_react7.Menu, { size: 20 }) }) : null,
1499
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { className: "frankie-thread-title", children: conversations.find((item) => item.id === currentId)?.title ?? messages.find((message) => message.role === "user")?.text ?? "New chat" })
1472
1500
  ] }),
1473
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
1474
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
1475
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.Plus, { size: 16 }),
1476
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "New chat" })
1501
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
1502
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", disabled: busy, onClick: onNew, "aria-label": "Start a new conversation", children: [
1503
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Plus, { size: 16 }),
1504
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "New chat" })
1477
1505
  ] }),
1478
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("details", { className: "frankie-chat-settings", children: [
1479
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.Settings, { size: 19 }) }),
1480
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
1481
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "Chat settings" }),
1482
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "History syncs automatically for signed-in users." }),
1483
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
1484
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.History, { size: 16 }),
1506
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("details", { className: "frankie-chat-settings", children: [
1507
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("summary", { "aria-label": "Chat settings", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Settings, { size: 19 }) }),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "Chat settings" }),
1510
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { children: "History syncs automatically for signed-in users." }),
1511
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", onClick: () => void refresh(), disabled: historyLoading || !showHistory, children: [
1512
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.History, { size: 16 }),
1485
1513
  "Refresh history"
1486
1514
  ] }),
1487
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("small", { children: "Skills are checked at the start of each message." })
1515
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("small", { children: "Skills are checked at the start of each message." })
1488
1516
  ] })
1489
1517
  ] })
1490
1518
  ] })
1491
1519
  ] }),
1492
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FrankieInline, { ...panel, header: panel.header ?? false, emptyState: panel.emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PageEmptyState, {}) }) })
1520
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "frankie-page-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FrankieInline, { ...panel, header: panel.header ?? false, emptyState: panel.emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PageEmptyState, {}) }) })
1493
1521
  ] }),
1494
- showHistory ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
1522
+ showHistory ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("dialog", { ref: dialog, className: "frankie-history-dialog frankie-root", "aria-label": "Chat conversations", style: themeToCssVars(theme), onCancel: close, onClick: (event) => {
1495
1523
  if (event.target === event.currentTarget) close();
1496
- }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("aside", { children: history }) }) : null
1524
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("aside", { children: history }) }) : null
1497
1525
  ] });
1498
1526
  }
1499
1527
  function FrankieChatPage({ className, style, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus, showHistory = true, navigation, ...provider }) {
1500
1528
  const [id, setId] = (0, import_react10.useState)(() => provider.conversationId ?? crypto.randomUUID());
1501
1529
  const onNew = () => setId(crypto.randomUUID());
1502
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: "min(36rem, 100dvh)", width: "100%", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
1530
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: ["frankie-root", "frankie-chat-page", className].filter(Boolean).join(" "), style: { height: "100%", minHeight: "min(36rem, 100dvh)", width: "100%", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FrankieProvider, { ...provider, conversationId: id, storageNamespace: (provider.storageNamespace ?? "frankie." + provider.publishableKey) + "." + id, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PageChrome, { showHistory, navigation, currentId: id, onSelect: setId, onNew, header, footer, emptyState, renderMessage, renderTool, placeholder, autoFocus }) }) });
1503
1531
  }
1504
1532
 
1505
1533
  // src/components/ui/separator.tsx
1506
- var import_jsx_runtime17 = require("react/jsx-runtime");
1534
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1507
1535
  function Separator({ className }) {
1508
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
1536
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "separator", className: cn("h-px w-full bg-border", className) });
1509
1537
  }
1510
1538
  // Annotate the CommonJS export names for ESM import in node:
1511
1539
  0 && (module.exports = {