strapi-plugin-ai-sdk 0.7.7 → 0.8.0

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.
Files changed (32) hide show
  1. package/dist/_chunks/{App-joEmdpxi.js → App-DTbAnq7K.js} +710 -51
  2. package/dist/_chunks/{App-DMdQymB3.mjs → App-DZVBmpvs.mjs} +712 -53
  3. package/dist/_chunks/{index-B7qLITWV.js → index-C3xn2IND.js} +1 -1
  4. package/dist/_chunks/{index-DrLcqX__.mjs → index-Ca2F2wBp.mjs} +1 -1
  5. package/dist/admin/index.js +1 -1
  6. package/dist/admin/index.mjs +1 -1
  7. package/dist/admin/src/components/NotePanel.d.ts +15 -0
  8. package/dist/admin/src/hooks/useNotes.d.ts +22 -0
  9. package/dist/admin/src/pages/NoteStorePage.d.ts +2 -0
  10. package/dist/admin/src/utils/notes-api.d.ts +28 -0
  11. package/dist/server/index.js +536 -121
  12. package/dist/server/index.mjs +536 -121
  13. package/dist/server/src/content-types/index.d.ts +46 -0
  14. package/dist/server/src/content-types/note/index.d.ts +47 -0
  15. package/dist/server/src/controllers/index.d.ts +9 -0
  16. package/dist/server/src/controllers/note.d.ts +12 -0
  17. package/dist/server/src/index.d.ts +55 -0
  18. package/dist/server/src/lib/trim-messages.d.ts +11 -0
  19. package/dist/server/src/mcp/resources/tool-guide.d.ts +5 -0
  20. package/dist/server/src/tool-logic/aggregate-content.d.ts +1 -1
  21. package/dist/server/src/tool-logic/create-content.d.ts +1 -1
  22. package/dist/server/src/tool-logic/find-one-content.d.ts +1 -1
  23. package/dist/server/src/tool-logic/index.d.ts +4 -0
  24. package/dist/server/src/tool-logic/list-content-types.d.ts +1 -1
  25. package/dist/server/src/tool-logic/manage-task.d.ts +1 -1
  26. package/dist/server/src/tool-logic/recall-notes.d.ts +22 -0
  27. package/dist/server/src/tool-logic/save-note.d.ts +17 -0
  28. package/dist/server/src/tool-logic/update-content.d.ts +1 -1
  29. package/dist/server/src/tool-logic/upload-media.d.ts +1 -1
  30. package/dist/server/src/tools/definitions/recall-notes.d.ts +2 -0
  31. package/dist/server/src/tools/definitions/save-note.d.ts +2 -0
  32. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { Layouts, Page } from "@strapi/strapi/admin";
3
3
  import { Link, useNavigate, Routes, Route } from "react-router-dom";
4
- import { Box, Typography, TextInput, Button, Main, SearchForm, Searchbar, Table, Thead, Tr, Th, Tbody, Td, Flex, Pagination, Modal, Field, Textarea, SingleSelect, SingleSelectOption } from "@strapi/design-system";
4
+ import { Box, Typography, Flex, Modal, Field, TextInput, Textarea, SingleSelect, SingleSelectOption, Button, Main, SearchForm, Searchbar, Table, Thead, Tr, Th, Tbody, Td, Pagination, Dialog } from "@strapi/design-system";
5
5
  import { useState, useEffect, useCallback, useMemo, useRef, forwardRef } from "react";
6
6
  import styled from "styled-components";
7
- import { P as PLUGIN_ID } from "./index-DrLcqX__.mjs";
8
- import { Plus, Trash, Sparkle, ArrowLeft, Pencil } from "@strapi/icons";
7
+ import { P as PLUGIN_ID } from "./index-Ca2F2wBp.mjs";
8
+ import { Plus, Trash, Sparkle, ArrowLeft, Pencil, WarningCircle } from "@strapi/icons";
9
9
  import Markdown from "react-markdown";
10
10
  import remarkGfm from "remark-gfm";
11
11
  const COOKIE_REGEX = /(?:^|;\s*)jwtToken=([^;]*)/;
@@ -205,40 +205,40 @@ function useChat(options) {
205
205
  }, []);
206
206
  return { messages, setMessages, sendMessage, clearMessages, isLoading, error };
207
207
  }
208
- const BASE$2 = () => `${getBackendURL()}/${PLUGIN_ID}/conversations`;
209
- function headers$2() {
208
+ const BASE$3 = () => `${getBackendURL()}/${PLUGIN_ID}/conversations`;
209
+ function headers$3() {
210
210
  const token = getToken();
211
211
  return {
212
212
  "Content-Type": "application/json",
213
213
  ...token ? { Authorization: `Bearer ${token}` } : {}
214
214
  };
215
215
  }
216
- async function request$2(url, init) {
217
- const res = await fetch(url, { headers: headers$2(), ...init });
216
+ async function request$3(url, init) {
217
+ const res = await fetch(url, { headers: headers$3(), ...init });
218
218
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
219
219
  const json = await res.json();
220
220
  return json.data;
221
221
  }
222
222
  function fetchConversations() {
223
- return request$2(BASE$2());
223
+ return request$3(BASE$3());
224
224
  }
225
225
  function fetchConversation(documentId) {
226
- return request$2(`${BASE$2()}/${documentId}`);
226
+ return request$3(`${BASE$3()}/${documentId}`);
227
227
  }
228
228
  function createConversation(data) {
229
- return request$2(BASE$2(), {
229
+ return request$3(BASE$3(), {
230
230
  method: "POST",
231
231
  body: JSON.stringify(data)
232
232
  });
233
233
  }
234
234
  function updateConversation(documentId, data) {
235
- return request$2(`${BASE$2()}/${documentId}`, {
235
+ return request$3(`${BASE$3()}/${documentId}`, {
236
236
  method: "PUT",
237
237
  body: JSON.stringify(data)
238
238
  });
239
239
  }
240
240
  function deleteConversation(documentId) {
241
- return request$2(`${BASE$2()}/${documentId}`, { method: "DELETE" });
241
+ return request$3(`${BASE$3()}/${documentId}`, { method: "DELETE" });
242
242
  }
243
243
  function useConversations() {
244
244
  const [conversations, setConversations] = useState([]);
@@ -326,37 +326,37 @@ function useConversations() {
326
326
  removeConversation
327
327
  };
328
328
  }
329
- const BASE$1 = () => `${getBackendURL()}/${PLUGIN_ID}/memories`;
330
- function headers$1() {
329
+ const BASE$2 = () => `${getBackendURL()}/${PLUGIN_ID}/memories`;
330
+ function headers$2() {
331
331
  const token = getToken();
332
332
  return {
333
333
  "Content-Type": "application/json",
334
334
  ...token ? { Authorization: `Bearer ${token}` } : {}
335
335
  };
336
336
  }
337
- async function request$1(url, init) {
338
- const res = await fetch(url, { headers: headers$1(), ...init });
337
+ async function request$2(url, init) {
338
+ const res = await fetch(url, { headers: headers$2(), ...init });
339
339
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
340
340
  const json = await res.json();
341
341
  return json.data;
342
342
  }
343
343
  function fetchMemories() {
344
- return request$1(BASE$1());
344
+ return request$2(BASE$2());
345
345
  }
346
346
  function createMemory(data) {
347
- return request$1(BASE$1(), {
347
+ return request$2(BASE$2(), {
348
348
  method: "POST",
349
349
  body: JSON.stringify(data)
350
350
  });
351
351
  }
352
352
  function updateMemory(documentId, data) {
353
- return request$1(`${BASE$1()}/${documentId}`, {
353
+ return request$2(`${BASE$2()}/${documentId}`, {
354
354
  method: "PUT",
355
355
  body: JSON.stringify(data)
356
356
  });
357
357
  }
358
358
  function deleteMemory(documentId) {
359
- return request$1(`${BASE$1()}/${documentId}`, { method: "DELETE" });
359
+ return request$2(`${BASE$2()}/${documentId}`, { method: "DELETE" });
360
360
  }
361
361
  function useMemories() {
362
362
  const [memories, setMemories] = useState([]);
@@ -402,6 +402,93 @@ function useMemories() {
402
402
  }, []);
403
403
  return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
404
404
  }
405
+ const BASE$1 = () => `${getBackendURL()}/${PLUGIN_ID}/notes`;
406
+ function headers$1() {
407
+ const token = getToken();
408
+ return {
409
+ "Content-Type": "application/json",
410
+ ...token ? { Authorization: `Bearer ${token}` } : {}
411
+ };
412
+ }
413
+ async function request$1(url, init) {
414
+ const res = await fetch(url, { headers: headers$1(), ...init });
415
+ if (!res.ok) throw new Error(`Request failed: ${res.status}`);
416
+ const json = await res.json();
417
+ return json.data;
418
+ }
419
+ function fetchNotes() {
420
+ return request$1(BASE$1());
421
+ }
422
+ function createNote(data) {
423
+ return request$1(BASE$1(), {
424
+ method: "POST",
425
+ body: JSON.stringify(data)
426
+ });
427
+ }
428
+ function updateNote(documentId, data) {
429
+ return request$1(`${BASE$1()}/${documentId}`, {
430
+ method: "PUT",
431
+ body: JSON.stringify(data)
432
+ });
433
+ }
434
+ function deleteNote(documentId) {
435
+ return request$1(`${BASE$1()}/${documentId}`, { method: "DELETE" });
436
+ }
437
+ function clearAllNotes() {
438
+ return request$1(`${BASE$1()}/clear`, { method: "DELETE" });
439
+ }
440
+ function useNotes() {
441
+ const [notes, setNotes] = useState([]);
442
+ const [loading, setLoading] = useState(true);
443
+ const load = useCallback(async () => {
444
+ try {
445
+ const data = await fetchNotes();
446
+ setNotes(data);
447
+ } catch (err) {
448
+ console.error("Failed to load notes:", err);
449
+ } finally {
450
+ setLoading(false);
451
+ }
452
+ }, []);
453
+ useEffect(() => {
454
+ load();
455
+ }, [load]);
456
+ const addNote = useCallback(async (data) => {
457
+ try {
458
+ const created = await createNote(data);
459
+ setNotes((prev) => [created, ...prev]);
460
+ } catch (err) {
461
+ console.error("Failed to create note:", err);
462
+ }
463
+ }, []);
464
+ const editNote = useCallback(async (documentId, data) => {
465
+ try {
466
+ const updated = await updateNote(documentId, data);
467
+ setNotes(
468
+ (prev) => prev.map((n) => n.documentId === documentId ? { ...n, ...updated } : n)
469
+ );
470
+ } catch (err) {
471
+ console.error("Failed to update note:", err);
472
+ }
473
+ }, []);
474
+ const removeNote = useCallback(async (documentId) => {
475
+ try {
476
+ await deleteNote(documentId);
477
+ setNotes((prev) => prev.filter((n) => n.documentId !== documentId));
478
+ } catch (err) {
479
+ console.error("Failed to delete note:", err);
480
+ }
481
+ }, []);
482
+ const clearAll = useCallback(async () => {
483
+ try {
484
+ await clearAllNotes();
485
+ setNotes([]);
486
+ } catch (err) {
487
+ console.error("Failed to clear notes:", err);
488
+ }
489
+ }, []);
490
+ return { notes, loading, addNote, editNote, removeNote, clearAll, refresh: load };
491
+ }
405
492
  const STORAGE_KEY = `${PLUGIN_ID}:enabledToolSources`;
406
493
  function useToolSources() {
407
494
  const [sources, setSources] = useState([]);
@@ -503,7 +590,7 @@ const ConversationItem = styled.button`
503
590
  opacity: 1;
504
591
  }
505
592
  `;
506
- const DeleteBtn$1 = styled.button`
593
+ const DeleteBtn$2 = styled.button`
507
594
  opacity: 0;
508
595
  transition: opacity 0.15s;
509
596
  flex-shrink: 0;
@@ -558,7 +645,7 @@ function ConversationSidebar({
558
645
  children: [
559
646
  /* @__PURE__ */ jsx(TitleText, { variant: "omega", textColor: "neutral800", children: conv.title }),
560
647
  /* @__PURE__ */ jsx(
561
- DeleteBtn$1,
648
+ DeleteBtn$2,
562
649
  {
563
650
  className: "delete-btn",
564
651
  onClick: (e) => {
@@ -577,7 +664,7 @@ function ConversationSidebar({
577
664
  ] })
578
665
  ] });
579
666
  }
580
- const PanelRoot = styled.div`
667
+ const PanelRoot$1 = styled.div`
581
668
  width: ${({ $open }) => $open ? "280px" : "0px"};
582
669
  min-width: ${({ $open }) => $open ? "280px" : "0px"};
583
670
  display: flex;
@@ -587,7 +674,7 @@ const PanelRoot = styled.div`
587
674
  overflow: hidden;
588
675
  transition: width 0.2s ease, min-width 0.2s ease;
589
676
  `;
590
- const PanelHeader = styled.div`
677
+ const PanelHeader$1 = styled.div`
591
678
  padding: 12px 16px;
592
679
  border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};
593
680
  `;
@@ -610,7 +697,7 @@ const MemoryContent = styled.div`
610
697
  flex: 1;
611
698
  min-width: 0;
612
699
  `;
613
- const CategoryBadge = styled.span`
700
+ const CategoryBadge$1 = styled.span`
614
701
  display: inline-block;
615
702
  font-size: 11px;
616
703
  padding: 1px 6px;
@@ -619,7 +706,7 @@ const CategoryBadge = styled.span`
619
706
  color: ${({ theme }) => theme.colors.neutral600};
620
707
  margin-bottom: 2px;
621
708
  `;
622
- const DeleteBtn = styled.button`
709
+ const DeleteBtn$1 = styled.button`
623
710
  opacity: 0;
624
711
  transition: opacity 0.15s;
625
712
  flex-shrink: 0;
@@ -647,8 +734,8 @@ const DeleteBtn = styled.button`
647
734
  }
648
735
  `;
649
736
  function MemoryPanel({ memories, open, onDelete }) {
650
- return /* @__PURE__ */ jsxs(PanelRoot, { $open: open, children: [
651
- /* @__PURE__ */ jsx(PanelHeader, { children: /* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral600", children: [
737
+ return /* @__PURE__ */ jsxs(PanelRoot$1, { $open: open, children: [
738
+ /* @__PURE__ */ jsx(PanelHeader$1, { children: /* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral600", children: [
652
739
  "MEMORIES (",
653
740
  memories.length,
654
741
  ")"
@@ -656,11 +743,11 @@ function MemoryPanel({ memories, open, onDelete }) {
656
743
  /* @__PURE__ */ jsxs(MemoryList, { children: [
657
744
  memories.map((mem) => /* @__PURE__ */ jsxs(MemoryItem, { children: [
658
745
  /* @__PURE__ */ jsxs(MemoryContent, { children: [
659
- /* @__PURE__ */ jsx(CategoryBadge, { children: mem.category }),
746
+ /* @__PURE__ */ jsx(CategoryBadge$1, { children: mem.category }),
660
747
  /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral800", style: { display: "block" }, children: mem.content })
661
748
  ] }),
662
749
  /* @__PURE__ */ jsx(
663
- DeleteBtn,
750
+ DeleteBtn$1,
664
751
  {
665
752
  className: "memory-delete",
666
753
  onClick: () => onDelete(mem.documentId),
@@ -673,6 +760,255 @@ function MemoryPanel({ memories, open, onDelete }) {
673
760
  ] })
674
761
  ] });
675
762
  }
763
+ const PanelRoot = styled.div`
764
+ width: ${({ $open }) => $open ? "300px" : "0px"};
765
+ min-width: ${({ $open }) => $open ? "300px" : "0px"};
766
+ display: flex;
767
+ flex-direction: column;
768
+ border-left: ${({ $open, theme }) => $open ? `1px solid ${theme.colors.neutral200}` : "none"};
769
+ background: ${({ theme }) => theme.colors.neutral100};
770
+ overflow: hidden;
771
+ transition: width 0.2s ease, min-width 0.2s ease;
772
+ `;
773
+ const PanelHeader = styled.div`
774
+ padding: 12px 16px;
775
+ border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};
776
+ `;
777
+ const NoteList = styled.div`
778
+ flex: 1;
779
+ overflow-y: auto;
780
+ padding: 8px 0;
781
+ `;
782
+ const NoteItem = styled.div`
783
+ display: flex;
784
+ align-items: flex-start;
785
+ gap: 8px;
786
+ padding: 8px 16px;
787
+ cursor: pointer;
788
+ border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
789
+
790
+ &:hover {
791
+ background: ${({ theme }) => theme.colors.neutral150};
792
+ }
793
+
794
+ &:hover .note-delete {
795
+ opacity: 1;
796
+ }
797
+ `;
798
+ const NoteContent = styled.div`
799
+ flex: 1;
800
+ min-width: 0;
801
+ `;
802
+ const CategoryBadge = styled.span`
803
+ display: inline-block;
804
+ font-size: 11px;
805
+ padding: 1px 6px;
806
+ border-radius: 3px;
807
+ background: ${({ theme }) => theme.colors.neutral200};
808
+ color: ${({ theme }) => theme.colors.neutral600};
809
+ margin-bottom: 2px;
810
+ `;
811
+ const TagsBadge = styled.span`
812
+ display: inline-block;
813
+ font-size: 10px;
814
+ padding: 1px 5px;
815
+ border-radius: 3px;
816
+ background: ${({ theme }) => theme.colors.primary100};
817
+ color: ${({ theme }) => theme.colors.primary600};
818
+ margin-left: 4px;
819
+ `;
820
+ const DeleteBtn = styled.button`
821
+ opacity: 0;
822
+ transition: opacity 0.15s;
823
+ flex-shrink: 0;
824
+ display: flex;
825
+ align-items: center;
826
+ justify-content: center;
827
+ width: 22px;
828
+ height: 22px;
829
+ margin-top: 2px;
830
+ padding: 0;
831
+ border: none;
832
+ border-radius: 4px;
833
+ background: transparent;
834
+ color: ${({ theme }) => theme.colors.neutral500};
835
+ cursor: pointer;
836
+
837
+ &:hover {
838
+ background: ${({ theme }) => theme.colors.neutral300};
839
+ color: ${({ theme }) => theme.colors.danger600};
840
+ }
841
+
842
+ svg {
843
+ width: 12px;
844
+ height: 12px;
845
+ }
846
+ `;
847
+ const NoteTitle = styled(Typography)`
848
+ display: block;
849
+ font-weight: 600;
850
+ margin-bottom: 2px;
851
+ `;
852
+ const NotePreview = styled(Typography)`
853
+ display: -webkit-box;
854
+ -webkit-line-clamp: 2;
855
+ -webkit-box-orient: vertical;
856
+ overflow: hidden;
857
+ `;
858
+ const WideModalContent$3 = styled(Modal.Content)`
859
+ max-width: 680px;
860
+ width: 100%;
861
+ `;
862
+ function EditNoteModal({ note, open, onClose, onSave }) {
863
+ const [title, setTitle] = useState("");
864
+ const [content, setContent] = useState("");
865
+ const [category, setCategory] = useState("research");
866
+ const [tags, setTags] = useState("");
867
+ const [source, setSource] = useState("");
868
+ useEffect(() => {
869
+ if (open && note) {
870
+ setTitle(note.title || "");
871
+ setContent(note.content);
872
+ setCategory(note.category);
873
+ setTags(note.tags || "");
874
+ setSource(note.source || "");
875
+ }
876
+ }, [open, note]);
877
+ const handleClose = () => {
878
+ onClose();
879
+ };
880
+ const handleSave = () => {
881
+ if (!note || !content.trim()) return;
882
+ onSave(note.documentId, { title, content, category, tags, source });
883
+ handleClose();
884
+ };
885
+ return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent$3, { children: [
886
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: "Edit Note" }) }),
887
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 5, width: "100%", children: [
888
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
889
+ /* @__PURE__ */ jsx(Field.Label, { children: "Title" }),
890
+ /* @__PURE__ */ jsx(
891
+ TextInput,
892
+ {
893
+ placeholder: "Short label for the note",
894
+ value: title,
895
+ onChange: (e) => setTitle(e.target.value)
896
+ }
897
+ )
898
+ ] }),
899
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
900
+ /* @__PURE__ */ jsx(Field.Label, { children: "Content" }),
901
+ /* @__PURE__ */ jsx(
902
+ Textarea,
903
+ {
904
+ placeholder: "Note content (supports markdown)",
905
+ value: content,
906
+ onChange: (e) => setContent(e.target.value),
907
+ style: { width: "100%", minHeight: "160px", fontFamily: "monospace" }
908
+ }
909
+ )
910
+ ] }),
911
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, width: "100%", children: [
912
+ /* @__PURE__ */ jsxs(Field.Root, { style: { flex: 1 }, children: [
913
+ /* @__PURE__ */ jsx(Field.Label, { children: "Category" }),
914
+ /* @__PURE__ */ jsxs(
915
+ SingleSelect,
916
+ {
917
+ value: category,
918
+ onChange: (value) => setCategory(value),
919
+ children: [
920
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "research", children: "Research" }),
921
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "snippet", children: "Snippet" }),
922
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "idea", children: "Idea" }),
923
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "reference", children: "Reference" })
924
+ ]
925
+ }
926
+ )
927
+ ] }),
928
+ /* @__PURE__ */ jsxs(Field.Root, { style: { flex: 1 }, children: [
929
+ /* @__PURE__ */ jsx(Field.Label, { children: "Source" }),
930
+ /* @__PURE__ */ jsx(
931
+ TextInput,
932
+ {
933
+ placeholder: "e.g. conversation, URL",
934
+ value: source,
935
+ onChange: (e) => setSource(e.target.value)
936
+ }
937
+ )
938
+ ] })
939
+ ] }),
940
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
941
+ /* @__PURE__ */ jsx(Field.Label, { children: "Tags" }),
942
+ /* @__PURE__ */ jsx(
943
+ TextInput,
944
+ {
945
+ placeholder: "Comma-separated tags",
946
+ value: tags,
947
+ onChange: (e) => setTags(e.target.value)
948
+ }
949
+ )
950
+ ] })
951
+ ] }) }),
952
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
953
+ /* @__PURE__ */ jsx(Modal.Close, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: "Cancel" }) }),
954
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: !content.trim(), children: "Save changes" })
955
+ ] })
956
+ ] }) });
957
+ }
958
+ function NotePanel({ notes, open, onDelete, onEdit }) {
959
+ const [editingNote, setEditingNote] = useState(null);
960
+ const handleNoteClick = (note) => {
961
+ setEditingNote(note);
962
+ };
963
+ const handleCloseModal = () => {
964
+ setEditingNote(null);
965
+ };
966
+ const handleSave = (documentId, data) => {
967
+ onEdit(documentId, data);
968
+ setEditingNote(null);
969
+ };
970
+ return /* @__PURE__ */ jsxs(PanelRoot, { $open: open, children: [
971
+ /* @__PURE__ */ jsx(PanelHeader, { children: /* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral600", children: [
972
+ "NOTES (",
973
+ notes.length,
974
+ ")"
975
+ ] }) }),
976
+ /* @__PURE__ */ jsxs(NoteList, { children: [
977
+ notes.map((note) => /* @__PURE__ */ jsxs(NoteItem, { onClick: () => handleNoteClick(note), children: [
978
+ /* @__PURE__ */ jsxs(NoteContent, { children: [
979
+ /* @__PURE__ */ jsxs(Flex, { gap: 1, wrap: "wrap", style: { marginBottom: 2 }, children: [
980
+ /* @__PURE__ */ jsx(CategoryBadge, { children: note.category }),
981
+ note.tags && note.tags.split(",").filter(Boolean).slice(0, 2).map((tag) => /* @__PURE__ */ jsx(TagsBadge, { children: tag.trim() }, tag.trim()))
982
+ ] }),
983
+ note.title && /* @__PURE__ */ jsx(NoteTitle, { variant: "omega", textColor: "neutral800", children: note.title }),
984
+ /* @__PURE__ */ jsx(NotePreview, { variant: "omega", textColor: "neutral600", children: note.content })
985
+ ] }),
986
+ /* @__PURE__ */ jsx(
987
+ DeleteBtn,
988
+ {
989
+ className: "note-delete",
990
+ onClick: (e) => {
991
+ e.stopPropagation();
992
+ onDelete(note.documentId);
993
+ },
994
+ "aria-label": "Delete note",
995
+ children: /* @__PURE__ */ jsx(Trash, {})
996
+ }
997
+ )
998
+ ] }, note.documentId)),
999
+ notes.length === 0 && /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral500", children: "No notes saved yet. Save research notes, snippets, and ideas during conversations." }) })
1000
+ ] }),
1001
+ /* @__PURE__ */ jsx(
1002
+ EditNoteModal,
1003
+ {
1004
+ note: editingNote,
1005
+ open: editingNote !== null,
1006
+ onClose: handleCloseModal,
1007
+ onSave: handleSave
1008
+ }
1009
+ )
1010
+ ] });
1011
+ }
676
1012
  const Wrapper = styled.div`
677
1013
  position: relative;
678
1014
  `;
@@ -1534,6 +1870,7 @@ function Chat() {
1534
1870
  const [input, setInput] = useState("");
1535
1871
  const [sidebarOpen, setSidebarOpen] = useState(false);
1536
1872
  const [memoryPanelOpen, setMemoryPanelOpen] = useState(false);
1873
+ const [notePanelOpen, setNotePanelOpen] = useState(false);
1537
1874
  const messagesEndRef = useRef(null);
1538
1875
  const prevIsLoadingRef = useRef(false);
1539
1876
  const {
@@ -1546,6 +1883,7 @@ function Chat() {
1546
1883
  removeConversation
1547
1884
  } = useConversations();
1548
1885
  const { memories, removeMemory, refresh: refreshMemories } = useMemories();
1886
+ const { notes, removeNote, editNote, refresh: refreshNotes } = useNotes();
1549
1887
  const { sources, enabledSources, enabledToolSources, toggleSource } = useToolSources();
1550
1888
  const { messages, sendMessage, isLoading, error } = useChat({
1551
1889
  initialMessages,
@@ -1556,9 +1894,10 @@ function Chat() {
1556
1894
  if (prevIsLoadingRef.current && !isLoading && messages.length > 0) {
1557
1895
  saveMessages(messages);
1558
1896
  refreshMemories();
1897
+ refreshNotes();
1559
1898
  }
1560
1899
  prevIsLoadingRef.current = isLoading;
1561
- }, [isLoading, messages, saveMessages, refreshMemories]);
1900
+ }, [isLoading, messages, saveMessages, refreshMemories, refreshNotes]);
1562
1901
  const handleSend = () => {
1563
1902
  if (!input.trim() || isLoading) return;
1564
1903
  sendMessage(input);
@@ -1600,6 +1939,18 @@ function Chat() {
1600
1939
  children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: /* @__PURE__ */ jsx("path", { d: "M2 4h12M2 8h12M2 12h8" }) })
1601
1940
  }
1602
1941
  ),
1942
+ /* @__PURE__ */ jsx(
1943
+ ToggleSidebarBtn,
1944
+ {
1945
+ onClick: () => navigate(`/plugins/${PLUGIN_ID}/note-store`),
1946
+ "aria-label": "Research Notes",
1947
+ children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
1948
+ /* @__PURE__ */ jsx("path", { d: "M4 2v12h8V5l-3-3H4z" }),
1949
+ /* @__PURE__ */ jsx("path", { d: "M9 2v3h3" }),
1950
+ /* @__PURE__ */ jsx("path", { d: "M6 8h4M6 10.5h4" })
1951
+ ] })
1952
+ }
1953
+ ),
1603
1954
  /* @__PURE__ */ jsx(
1604
1955
  ToggleSidebarBtn,
1605
1956
  {
@@ -1633,6 +1984,18 @@ function Chat() {
1633
1984
  }
1634
1985
  ),
1635
1986
  /* @__PURE__ */ jsx("div", { style: { flex: 1 } }),
1987
+ /* @__PURE__ */ jsx(
1988
+ ToggleSidebarBtn,
1989
+ {
1990
+ onClick: () => setNotePanelOpen((prev) => !prev),
1991
+ "aria-label": notePanelOpen ? "Hide notes" : "Show notes",
1992
+ children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
1993
+ /* @__PURE__ */ jsx("path", { d: "M4 2v12h8V5l-3-3H4z" }),
1994
+ /* @__PURE__ */ jsx("path", { d: "M9 2v3h3" }),
1995
+ /* @__PURE__ */ jsx("path", { d: "M6 8h4M6 10.5h4" })
1996
+ ] })
1997
+ }
1998
+ ),
1636
1999
  /* @__PURE__ */ jsx(
1637
2000
  ToggleSidebarBtn,
1638
2001
  {
@@ -1667,6 +2030,15 @@ function Chat() {
1667
2030
  }
1668
2031
  )
1669
2032
  ] }),
2033
+ /* @__PURE__ */ jsx(
2034
+ NotePanel,
2035
+ {
2036
+ notes,
2037
+ open: notePanelOpen,
2038
+ onDelete: removeNote,
2039
+ onEdit: editNote
2040
+ }
2041
+ ),
1670
2042
  /* @__PURE__ */ jsx(
1671
2043
  MemoryPanel,
1672
2044
  {
@@ -1689,8 +2061,8 @@ const HomePage = () => {
1689
2061
  /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(Chat, {}) })
1690
2062
  ] });
1691
2063
  };
1692
- const PAGE_SIZE$1 = 10;
1693
- const ActionBtn$1 = styled.button`
2064
+ const PAGE_SIZE$2 = 10;
2065
+ const ActionBtn$2 = styled.button`
1694
2066
  display: inline-flex;
1695
2067
  align-items: center;
1696
2068
  justify-content: center;
@@ -1713,16 +2085,16 @@ const ActionBtn$1 = styled.button`
1713
2085
  height: 16px;
1714
2086
  }
1715
2087
  `;
1716
- const DeleteActionBtn$1 = styled(ActionBtn$1)`
2088
+ const DeleteActionBtn$2 = styled(ActionBtn$2)`
1717
2089
  &:hover {
1718
2090
  color: ${({ theme }) => theme.colors.danger600};
1719
2091
  }
1720
2092
  `;
1721
- const WideModalContent$1 = styled(Modal.Content)`
2093
+ const WideModalContent$2 = styled(Modal.Content)`
1722
2094
  max-width: 680px;
1723
2095
  width: 100%;
1724
2096
  `;
1725
- function formatDate$1(iso) {
2097
+ function formatDate$2(iso) {
1726
2098
  return new Date(iso).toLocaleDateString(void 0, {
1727
2099
  year: "numeric",
1728
2100
  month: "short",
@@ -1754,7 +2126,7 @@ function MemoryModal({ memory, open, onClose, onSave }) {
1754
2126
  onSave({ content, category }, memory?.documentId);
1755
2127
  handleClose();
1756
2128
  };
1757
- return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent$1, { children: [
2129
+ return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent$2, { children: [
1758
2130
  /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: isEdit ? "Edit Memory" : "Add Memory" }) }),
1759
2131
  /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 5, width: "100%", children: [
1760
2132
  /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
@@ -1807,8 +2179,8 @@ const MemoryStorePage = () => {
1807
2179
  (m) => m.content.toLowerCase().includes(q) || m.category.toLowerCase().includes(q)
1808
2180
  );
1809
2181
  }, [memories, search]);
1810
- const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$1));
1811
- const paginated = filtered.slice((page - 1) * PAGE_SIZE$1, page * PAGE_SIZE$1);
2182
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$2));
2183
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE$2, page * PAGE_SIZE$2);
1812
2184
  const handleOpenCreate = () => {
1813
2185
  setEditingMemory(null);
1814
2186
  setModalOpen(true);
@@ -1869,10 +2241,10 @@ const MemoryStorePage = () => {
1869
2241
  paginated.map((mem) => /* @__PURE__ */ jsxs(Tr, { children: [
1870
2242
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", children: mem.content }) }),
1871
2243
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: mem.category }) }),
1872
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatDate$1(mem.createdAt) }) }),
2244
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatDate$2(mem.createdAt) }) }),
1873
2245
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
1874
2246
  /* @__PURE__ */ jsx(
1875
- ActionBtn$1,
2247
+ ActionBtn$2,
1876
2248
  {
1877
2249
  onClick: () => handleOpenEdit(mem),
1878
2250
  "aria-label": "Edit memory",
@@ -1880,7 +2252,7 @@ const MemoryStorePage = () => {
1880
2252
  }
1881
2253
  ),
1882
2254
  /* @__PURE__ */ jsx(
1883
- DeleteActionBtn$1,
2255
+ DeleteActionBtn$2,
1884
2256
  {
1885
2257
  onClick: () => removeMemory(mem.documentId),
1886
2258
  "aria-label": "Delete memory",
@@ -1980,8 +2352,8 @@ function usePublicMemories() {
1980
2352
  }, []);
1981
2353
  return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
1982
2354
  }
1983
- const PAGE_SIZE = 10;
1984
- const ActionBtn = styled.button`
2355
+ const PAGE_SIZE$1 = 10;
2356
+ const ActionBtn$1 = styled.button`
1985
2357
  display: inline-flex;
1986
2358
  align-items: center;
1987
2359
  justify-content: center;
@@ -2004,16 +2376,16 @@ const ActionBtn = styled.button`
2004
2376
  height: 16px;
2005
2377
  }
2006
2378
  `;
2007
- const DeleteActionBtn = styled(ActionBtn)`
2379
+ const DeleteActionBtn$1 = styled(ActionBtn$1)`
2008
2380
  &:hover {
2009
2381
  color: ${({ theme }) => theme.colors.danger600};
2010
2382
  }
2011
2383
  `;
2012
- const WideModalContent = styled(Modal.Content)`
2384
+ const WideModalContent$1 = styled(Modal.Content)`
2013
2385
  max-width: 680px;
2014
2386
  width: 100%;
2015
2387
  `;
2016
- function formatDate(iso) {
2388
+ function formatDate$1(iso) {
2017
2389
  return new Date(iso).toLocaleDateString(void 0, {
2018
2390
  year: "numeric",
2019
2391
  month: "short",
@@ -2045,7 +2417,7 @@ function PublicMemoryModal({ memory, open, onClose, onSave }) {
2045
2417
  onSave({ content, category }, memory?.documentId);
2046
2418
  handleClose();
2047
2419
  };
2048
- return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent, { children: [
2420
+ return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent$1, { children: [
2049
2421
  /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: isEdit ? "Edit Public Memory" : "Add Public Memory" }) }),
2050
2422
  /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 5, width: "100%", children: [
2051
2423
  /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
@@ -2098,8 +2470,8 @@ const PublicMemoryStorePage = () => {
2098
2470
  (m) => m.content.toLowerCase().includes(q) || m.category.toLowerCase().includes(q)
2099
2471
  );
2100
2472
  }, [memories, search]);
2101
- const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2102
- const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2473
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$1));
2474
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE$1, page * PAGE_SIZE$1);
2103
2475
  const handleOpenCreate = () => {
2104
2476
  setEditingMemory(null);
2105
2477
  setModalOpen(true);
@@ -2160,10 +2532,10 @@ const PublicMemoryStorePage = () => {
2160
2532
  paginated.map((mem) => /* @__PURE__ */ jsxs(Tr, { children: [
2161
2533
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", children: mem.content }) }),
2162
2534
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: mem.category }) }),
2163
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatDate(mem.createdAt) }) }),
2535
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatDate$1(mem.createdAt) }) }),
2164
2536
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
2165
2537
  /* @__PURE__ */ jsx(
2166
- ActionBtn,
2538
+ ActionBtn$1,
2167
2539
  {
2168
2540
  onClick: () => handleOpenEdit(mem),
2169
2541
  "aria-label": "Edit memory",
@@ -2171,7 +2543,7 @@ const PublicMemoryStorePage = () => {
2171
2543
  }
2172
2544
  ),
2173
2545
  /* @__PURE__ */ jsx(
2174
- DeleteActionBtn,
2546
+ DeleteActionBtn$1,
2175
2547
  {
2176
2548
  onClick: () => removeMemory(mem.documentId),
2177
2549
  "aria-label": "Delete memory",
@@ -2195,6 +2567,292 @@ const PublicMemoryStorePage = () => {
2195
2567
  ] })
2196
2568
  ] });
2197
2569
  };
2570
+ const PAGE_SIZE = 10;
2571
+ const ActionBtn = styled.button`
2572
+ display: inline-flex;
2573
+ align-items: center;
2574
+ justify-content: center;
2575
+ width: 32px;
2576
+ height: 32px;
2577
+ padding: 0;
2578
+ border: none;
2579
+ border-radius: 4px;
2580
+ background: transparent;
2581
+ color: ${({ theme }) => theme.colors.neutral600};
2582
+ cursor: pointer;
2583
+
2584
+ &:hover {
2585
+ background: ${({ theme }) => theme.colors.neutral200};
2586
+ color: ${({ theme }) => theme.colors.primary600};
2587
+ }
2588
+
2589
+ svg {
2590
+ width: 16px;
2591
+ height: 16px;
2592
+ }
2593
+ `;
2594
+ const DeleteActionBtn = styled(ActionBtn)`
2595
+ &:hover {
2596
+ color: ${({ theme }) => theme.colors.danger600};
2597
+ }
2598
+ `;
2599
+ const WideModalContent = styled(Modal.Content)`
2600
+ max-width: 680px;
2601
+ width: 100%;
2602
+ `;
2603
+ function formatDate(iso) {
2604
+ return new Date(iso).toLocaleDateString(void 0, {
2605
+ year: "numeric",
2606
+ month: "short",
2607
+ day: "numeric",
2608
+ hour: "2-digit",
2609
+ minute: "2-digit"
2610
+ });
2611
+ }
2612
+ function NoteModal({ note, open, onClose, onSave }) {
2613
+ const [title, setTitle] = useState("");
2614
+ const [content, setContent] = useState("");
2615
+ const [category, setCategory] = useState("research");
2616
+ const [tags, setTags] = useState("");
2617
+ const [source, setSource] = useState("");
2618
+ const isEdit = note !== null;
2619
+ useEffect(() => {
2620
+ if (open && note) {
2621
+ setTitle(note.title || "");
2622
+ setContent(note.content);
2623
+ setCategory(note.category);
2624
+ setTags(note.tags || "");
2625
+ setSource(note.source || "");
2626
+ } else if (open) {
2627
+ setTitle("");
2628
+ setContent("");
2629
+ setCategory("research");
2630
+ setTags("");
2631
+ setSource("");
2632
+ }
2633
+ }, [open, note]);
2634
+ const handleClose = () => {
2635
+ setTitle("");
2636
+ setContent("");
2637
+ setCategory("research");
2638
+ setTags("");
2639
+ setSource("");
2640
+ onClose();
2641
+ };
2642
+ const handleSave = () => {
2643
+ if (!content.trim()) return;
2644
+ onSave({ title, content, category, tags, source }, note?.documentId);
2645
+ handleClose();
2646
+ };
2647
+ return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(WideModalContent, { children: [
2648
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: isEdit ? "Edit Note" : "Add Note" }) }),
2649
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 5, width: "100%", children: [
2650
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
2651
+ /* @__PURE__ */ jsx(Field.Label, { children: "Title" }),
2652
+ /* @__PURE__ */ jsx(
2653
+ TextInput,
2654
+ {
2655
+ placeholder: "Short label for the note",
2656
+ value: title,
2657
+ onChange: (e) => setTitle(e.target.value)
2658
+ }
2659
+ )
2660
+ ] }),
2661
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
2662
+ /* @__PURE__ */ jsx(Field.Label, { children: "Content" }),
2663
+ /* @__PURE__ */ jsx(
2664
+ Textarea,
2665
+ {
2666
+ placeholder: "Note content (supports markdown)",
2667
+ value: content,
2668
+ onChange: (e) => setContent(e.target.value),
2669
+ style: { width: "100%", minHeight: "160px", maxHeight: "300px", overflow: "auto", fontFamily: "monospace" }
2670
+ }
2671
+ )
2672
+ ] }),
2673
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, width: "100%", children: [
2674
+ /* @__PURE__ */ jsxs(Field.Root, { style: { flex: 1 }, children: [
2675
+ /* @__PURE__ */ jsx(Field.Label, { children: "Category" }),
2676
+ /* @__PURE__ */ jsxs(
2677
+ SingleSelect,
2678
+ {
2679
+ value: category,
2680
+ onChange: (value) => setCategory(value),
2681
+ children: [
2682
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "research", children: "Research" }),
2683
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "snippet", children: "Snippet" }),
2684
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "idea", children: "Idea" }),
2685
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "reference", children: "Reference" })
2686
+ ]
2687
+ }
2688
+ )
2689
+ ] }),
2690
+ /* @__PURE__ */ jsxs(Field.Root, { style: { flex: 1 }, children: [
2691
+ /* @__PURE__ */ jsx(Field.Label, { children: "Source" }),
2692
+ /* @__PURE__ */ jsx(
2693
+ TextInput,
2694
+ {
2695
+ placeholder: "e.g. conversation, URL",
2696
+ value: source,
2697
+ onChange: (e) => setSource(e.target.value)
2698
+ }
2699
+ )
2700
+ ] })
2701
+ ] }),
2702
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
2703
+ /* @__PURE__ */ jsx(Field.Label, { children: "Tags" }),
2704
+ /* @__PURE__ */ jsx(
2705
+ TextInput,
2706
+ {
2707
+ placeholder: "Comma-separated tags (e.g. strapi, api, tutorial)",
2708
+ value: tags,
2709
+ onChange: (e) => setTags(e.target.value)
2710
+ }
2711
+ ),
2712
+ /* @__PURE__ */ jsx(Field.Hint, { children: "Used to filter and organize notes" })
2713
+ ] })
2714
+ ] }) }),
2715
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
2716
+ /* @__PURE__ */ jsx(Modal.Close, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: "Cancel" }) }),
2717
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: !content.trim(), children: isEdit ? "Save changes" : "Add note" })
2718
+ ] })
2719
+ ] }) });
2720
+ }
2721
+ const NoteStorePage = () => {
2722
+ const navigate = useNavigate();
2723
+ const { notes, loading, addNote, editNote, removeNote, clearAll } = useNotes();
2724
+ const [search, setSearch] = useState("");
2725
+ const [page, setPage] = useState(1);
2726
+ const [modalOpen, setModalOpen] = useState(false);
2727
+ const [editingNote, setEditingNote] = useState(null);
2728
+ const [clearDialogOpen, setClearDialogOpen] = useState(false);
2729
+ const filtered = useMemo(() => {
2730
+ if (!search.trim()) return notes;
2731
+ const q = search.toLowerCase();
2732
+ return notes.filter(
2733
+ (n) => (n.title || "").toLowerCase().includes(q) || n.content.toLowerCase().includes(q) || n.category.toLowerCase().includes(q) || (n.tags || "").toLowerCase().includes(q)
2734
+ );
2735
+ }, [notes, search]);
2736
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2737
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2738
+ const handleOpenCreate = () => {
2739
+ setEditingNote(null);
2740
+ setModalOpen(true);
2741
+ };
2742
+ const handleOpenEdit = (note) => {
2743
+ setEditingNote(note);
2744
+ setModalOpen(true);
2745
+ };
2746
+ const handleCloseModal = () => {
2747
+ setModalOpen(false);
2748
+ setEditingNote(null);
2749
+ };
2750
+ const handleSave = (data, documentId) => {
2751
+ if (documentId) {
2752
+ editNote(documentId, data);
2753
+ } else {
2754
+ addNote(data);
2755
+ }
2756
+ };
2757
+ const handleClearAll = () => {
2758
+ clearAll();
2759
+ setClearDialogOpen(false);
2760
+ };
2761
+ return /* @__PURE__ */ jsxs(Main, { children: [
2762
+ /* @__PURE__ */ jsx(
2763
+ Layouts.Header,
2764
+ {
2765
+ title: "Research Notes",
2766
+ subtitle: `${notes.length} notes saved`,
2767
+ primaryAction: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2768
+ /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: () => setClearDialogOpen(true), disabled: notes.length === 0, children: "Clear all" }),
2769
+ /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: handleOpenCreate, children: "Add note" })
2770
+ ] }),
2771
+ navigationAction: /* @__PURE__ */ jsx(Button, { variant: "ghost", startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), onClick: () => navigate(`/plugins/${PLUGIN_ID}`), children: "Back to Chat" })
2772
+ }
2773
+ ),
2774
+ /* @__PURE__ */ jsxs(Layouts.Content, { children: [
2775
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(SearchForm, { children: /* @__PURE__ */ jsx(
2776
+ Searchbar,
2777
+ {
2778
+ name: "search",
2779
+ value: search,
2780
+ onChange: (e) => {
2781
+ setSearch(e.target.value);
2782
+ setPage(1);
2783
+ },
2784
+ onClear: () => {
2785
+ setSearch("");
2786
+ setPage(1);
2787
+ },
2788
+ placeholder: "Search notes...",
2789
+ children: "Search"
2790
+ }
2791
+ ) }) }),
2792
+ /* @__PURE__ */ jsxs(Table, { colCount: 6, rowCount: paginated.length + 1, children: [
2793
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
2794
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Title" }) }),
2795
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Content" }) }),
2796
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Category" }) }),
2797
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Tags" }) }),
2798
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Created" }) }),
2799
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Actions" }) })
2800
+ ] }) }),
2801
+ /* @__PURE__ */ jsxs(Tbody, { children: [
2802
+ loading && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 6, children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: "Loading..." }) }) }) }),
2803
+ !loading && paginated.length === 0 && /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 6, children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral500", children: search ? "No notes match your search" : "No notes saved yet. Save research notes, snippets, and ideas during conversations." }) }) }) }),
2804
+ paginated.map((note) => /* @__PURE__ */ jsxs(Tr, { children: [
2805
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", fontWeight: "semiBold", children: note.title || "—" }) }),
2806
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: note.content.length > 100 ? `${note.content.slice(0, 100)}...` : note.content }) }),
2807
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: note.category }) }),
2808
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: note.tags || "—" }) }),
2809
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatDate(note.createdAt) }) }),
2810
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
2811
+ /* @__PURE__ */ jsx(
2812
+ ActionBtn,
2813
+ {
2814
+ onClick: () => handleOpenEdit(note),
2815
+ "aria-label": "Edit note",
2816
+ children: /* @__PURE__ */ jsx(Pencil, {})
2817
+ }
2818
+ ),
2819
+ /* @__PURE__ */ jsx(
2820
+ DeleteActionBtn,
2821
+ {
2822
+ onClick: () => removeNote(note.documentId),
2823
+ "aria-label": "Delete note",
2824
+ children: /* @__PURE__ */ jsx(Trash, {})
2825
+ }
2826
+ )
2827
+ ] }) })
2828
+ ] }, note.documentId))
2829
+ ] })
2830
+ ] }),
2831
+ pageCount > 1 && /* @__PURE__ */ jsx(Box, { paddingTop: 4, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Pagination.Root, { pageCount, activePage: page, onPageChange: setPage, children: /* @__PURE__ */ jsx(Pagination.Links, {}) }) }) }),
2832
+ /* @__PURE__ */ jsx(
2833
+ NoteModal,
2834
+ {
2835
+ note: editingNote,
2836
+ open: modalOpen,
2837
+ onClose: handleCloseModal,
2838
+ onSave: handleSave
2839
+ }
2840
+ ),
2841
+ /* @__PURE__ */ jsx(Dialog.Root, { open: clearDialogOpen, onOpenChange: setClearDialogOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2842
+ /* @__PURE__ */ jsx(Dialog.Header, { children: "Clear all notes" }),
2843
+ /* @__PURE__ */ jsxs(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: [
2844
+ "Are you sure you want to delete all ",
2845
+ notes.length,
2846
+ " notes? This action cannot be undone."
2847
+ ] }),
2848
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
2849
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: "Cancel" }) }),
2850
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: handleClearAll, children: "Clear all" }) })
2851
+ ] })
2852
+ ] }) })
2853
+ ] })
2854
+ ] });
2855
+ };
2198
2856
  function getStrapiOrigin() {
2199
2857
  return globalThis.location.origin;
2200
2858
  }
@@ -2344,6 +3002,7 @@ const App = () => {
2344
3002
  /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(HomePage, {}) }),
2345
3003
  /* @__PURE__ */ jsx(Route, { path: "memory-store", element: /* @__PURE__ */ jsx(MemoryStorePage, {}) }),
2346
3004
  /* @__PURE__ */ jsx(Route, { path: "public-memory-store", element: /* @__PURE__ */ jsx(PublicMemoryStorePage, {}) }),
3005
+ /* @__PURE__ */ jsx(Route, { path: "note-store", element: /* @__PURE__ */ jsx(NoteStorePage, {}) }),
2347
3006
  /* @__PURE__ */ jsx(Route, { path: "widget-preview", element: /* @__PURE__ */ jsx(WidgetPreviewPage, {}) }),
2348
3007
  /* @__PURE__ */ jsx(Route, { path: "*", element: /* @__PURE__ */ jsx(Page.Error, {}) })
2349
3008
  ] });