strapi-plugin-ai-sdk 0.7.4 → 0.7.9

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 (34) hide show
  1. package/dist/_chunks/{App-CEEsJsKL.js → App-DTbAnq7K.js} +712 -53
  2. package/dist/_chunks/{App-DCV7o6Hc.mjs → App-DZVBmpvs.mjs} +714 -55
  3. package/dist/_chunks/{index-Cw2aiQ8K.js → index-C3xn2IND.js} +1 -1
  4. package/dist/_chunks/{index-BMrDQVQl.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 +603 -171
  12. package/dist/server/index.mjs +603 -171
  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/mcp/resources/tool-guide.d.ts +5 -0
  19. package/dist/server/src/tool-logic/aggregate-content.d.ts +1 -1
  20. package/dist/server/src/tool-logic/create-content.d.ts +27 -0
  21. package/dist/server/src/tool-logic/find-one-content.d.ts +1 -1
  22. package/dist/server/src/tool-logic/index.d.ts +8 -2
  23. package/dist/server/src/tool-logic/list-content-types.d.ts +1 -1
  24. package/dist/server/src/tool-logic/manage-task.d.ts +1 -1
  25. package/dist/server/src/tool-logic/recall-notes.d.ts +22 -0
  26. package/dist/server/src/tool-logic/save-note.d.ts +17 -0
  27. package/dist/server/src/tool-logic/update-content.d.ts +29 -0
  28. package/dist/server/src/tool-logic/upload-media.d.ts +1 -1
  29. package/dist/server/src/tools/definitions/create-content.d.ts +2 -0
  30. package/dist/server/src/tools/definitions/{write-content.d.ts → recall-notes.d.ts} +1 -1
  31. package/dist/server/src/tools/definitions/save-note.d.ts +2 -0
  32. package/dist/server/src/tools/definitions/update-content.d.ts +2 -0
  33. package/package.json +1 -1
  34. package/dist/server/src/tool-logic/write-content.d.ts +0 -34
@@ -6,7 +6,7 @@ const reactRouterDom = require("react-router-dom");
6
6
  const designSystem = require("@strapi/design-system");
7
7
  const react = require("react");
8
8
  const styled = require("styled-components");
9
- const index = require("./index-Cw2aiQ8K.js");
9
+ const index = require("./index-C3xn2IND.js");
10
10
  const icons = require("@strapi/icons");
11
11
  const Markdown = require("react-markdown");
12
12
  const remarkGfm = require("remark-gfm");
@@ -211,40 +211,40 @@ function useChat(options) {
211
211
  }, []);
212
212
  return { messages, setMessages, sendMessage, clearMessages, isLoading, error };
213
213
  }
214
- const BASE$2 = () => `${getBackendURL()}/${index.PLUGIN_ID}/conversations`;
215
- function headers$2() {
214
+ const BASE$3 = () => `${getBackendURL()}/${index.PLUGIN_ID}/conversations`;
215
+ function headers$3() {
216
216
  const token = getToken();
217
217
  return {
218
218
  "Content-Type": "application/json",
219
219
  ...token ? { Authorization: `Bearer ${token}` } : {}
220
220
  };
221
221
  }
222
- async function request$2(url, init) {
223
- const res = await fetch(url, { headers: headers$2(), ...init });
222
+ async function request$3(url, init) {
223
+ const res = await fetch(url, { headers: headers$3(), ...init });
224
224
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
225
225
  const json = await res.json();
226
226
  return json.data;
227
227
  }
228
228
  function fetchConversations() {
229
- return request$2(BASE$2());
229
+ return request$3(BASE$3());
230
230
  }
231
231
  function fetchConversation(documentId) {
232
- return request$2(`${BASE$2()}/${documentId}`);
232
+ return request$3(`${BASE$3()}/${documentId}`);
233
233
  }
234
234
  function createConversation(data) {
235
- return request$2(BASE$2(), {
235
+ return request$3(BASE$3(), {
236
236
  method: "POST",
237
237
  body: JSON.stringify(data)
238
238
  });
239
239
  }
240
240
  function updateConversation(documentId, data) {
241
- return request$2(`${BASE$2()}/${documentId}`, {
241
+ return request$3(`${BASE$3()}/${documentId}`, {
242
242
  method: "PUT",
243
243
  body: JSON.stringify(data)
244
244
  });
245
245
  }
246
246
  function deleteConversation(documentId) {
247
- return request$2(`${BASE$2()}/${documentId}`, { method: "DELETE" });
247
+ return request$3(`${BASE$3()}/${documentId}`, { method: "DELETE" });
248
248
  }
249
249
  function useConversations() {
250
250
  const [conversations, setConversations] = react.useState([]);
@@ -332,37 +332,37 @@ function useConversations() {
332
332
  removeConversation
333
333
  };
334
334
  }
335
- const BASE$1 = () => `${getBackendURL()}/${index.PLUGIN_ID}/memories`;
336
- function headers$1() {
335
+ const BASE$2 = () => `${getBackendURL()}/${index.PLUGIN_ID}/memories`;
336
+ function headers$2() {
337
337
  const token = getToken();
338
338
  return {
339
339
  "Content-Type": "application/json",
340
340
  ...token ? { Authorization: `Bearer ${token}` } : {}
341
341
  };
342
342
  }
343
- async function request$1(url, init) {
344
- const res = await fetch(url, { headers: headers$1(), ...init });
343
+ async function request$2(url, init) {
344
+ const res = await fetch(url, { headers: headers$2(), ...init });
345
345
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
346
346
  const json = await res.json();
347
347
  return json.data;
348
348
  }
349
349
  function fetchMemories() {
350
- return request$1(BASE$1());
350
+ return request$2(BASE$2());
351
351
  }
352
352
  function createMemory(data) {
353
- return request$1(BASE$1(), {
353
+ return request$2(BASE$2(), {
354
354
  method: "POST",
355
355
  body: JSON.stringify(data)
356
356
  });
357
357
  }
358
358
  function updateMemory(documentId, data) {
359
- return request$1(`${BASE$1()}/${documentId}`, {
359
+ return request$2(`${BASE$2()}/${documentId}`, {
360
360
  method: "PUT",
361
361
  body: JSON.stringify(data)
362
362
  });
363
363
  }
364
364
  function deleteMemory(documentId) {
365
- return request$1(`${BASE$1()}/${documentId}`, { method: "DELETE" });
365
+ return request$2(`${BASE$2()}/${documentId}`, { method: "DELETE" });
366
366
  }
367
367
  function useMemories() {
368
368
  const [memories, setMemories] = react.useState([]);
@@ -408,6 +408,93 @@ function useMemories() {
408
408
  }, []);
409
409
  return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
410
410
  }
411
+ const BASE$1 = () => `${getBackendURL()}/${index.PLUGIN_ID}/notes`;
412
+ function headers$1() {
413
+ const token = getToken();
414
+ return {
415
+ "Content-Type": "application/json",
416
+ ...token ? { Authorization: `Bearer ${token}` } : {}
417
+ };
418
+ }
419
+ async function request$1(url, init) {
420
+ const res = await fetch(url, { headers: headers$1(), ...init });
421
+ if (!res.ok) throw new Error(`Request failed: ${res.status}`);
422
+ const json = await res.json();
423
+ return json.data;
424
+ }
425
+ function fetchNotes() {
426
+ return request$1(BASE$1());
427
+ }
428
+ function createNote(data) {
429
+ return request$1(BASE$1(), {
430
+ method: "POST",
431
+ body: JSON.stringify(data)
432
+ });
433
+ }
434
+ function updateNote(documentId, data) {
435
+ return request$1(`${BASE$1()}/${documentId}`, {
436
+ method: "PUT",
437
+ body: JSON.stringify(data)
438
+ });
439
+ }
440
+ function deleteNote(documentId) {
441
+ return request$1(`${BASE$1()}/${documentId}`, { method: "DELETE" });
442
+ }
443
+ function clearAllNotes() {
444
+ return request$1(`${BASE$1()}/clear`, { method: "DELETE" });
445
+ }
446
+ function useNotes() {
447
+ const [notes, setNotes] = react.useState([]);
448
+ const [loading, setLoading] = react.useState(true);
449
+ const load = react.useCallback(async () => {
450
+ try {
451
+ const data = await fetchNotes();
452
+ setNotes(data);
453
+ } catch (err) {
454
+ console.error("Failed to load notes:", err);
455
+ } finally {
456
+ setLoading(false);
457
+ }
458
+ }, []);
459
+ react.useEffect(() => {
460
+ load();
461
+ }, [load]);
462
+ const addNote = react.useCallback(async (data) => {
463
+ try {
464
+ const created = await createNote(data);
465
+ setNotes((prev) => [created, ...prev]);
466
+ } catch (err) {
467
+ console.error("Failed to create note:", err);
468
+ }
469
+ }, []);
470
+ const editNote = react.useCallback(async (documentId, data) => {
471
+ try {
472
+ const updated = await updateNote(documentId, data);
473
+ setNotes(
474
+ (prev) => prev.map((n) => n.documentId === documentId ? { ...n, ...updated } : n)
475
+ );
476
+ } catch (err) {
477
+ console.error("Failed to update note:", err);
478
+ }
479
+ }, []);
480
+ const removeNote = react.useCallback(async (documentId) => {
481
+ try {
482
+ await deleteNote(documentId);
483
+ setNotes((prev) => prev.filter((n) => n.documentId !== documentId));
484
+ } catch (err) {
485
+ console.error("Failed to delete note:", err);
486
+ }
487
+ }, []);
488
+ const clearAll = react.useCallback(async () => {
489
+ try {
490
+ await clearAllNotes();
491
+ setNotes([]);
492
+ } catch (err) {
493
+ console.error("Failed to clear notes:", err);
494
+ }
495
+ }, []);
496
+ return { notes, loading, addNote, editNote, removeNote, clearAll, refresh: load };
497
+ }
411
498
  const STORAGE_KEY = `${index.PLUGIN_ID}:enabledToolSources`;
412
499
  function useToolSources() {
413
500
  const [sources, setSources] = react.useState([]);
@@ -509,7 +596,7 @@ const ConversationItem = styled__default.default.button`
509
596
  opacity: 1;
510
597
  }
511
598
  `;
512
- const DeleteBtn$1 = styled__default.default.button`
599
+ const DeleteBtn$2 = styled__default.default.button`
513
600
  opacity: 0;
514
601
  transition: opacity 0.15s;
515
602
  flex-shrink: 0;
@@ -564,7 +651,7 @@ function ConversationSidebar({
564
651
  children: [
565
652
  /* @__PURE__ */ jsxRuntime.jsx(TitleText, { variant: "omega", textColor: "neutral800", children: conv.title }),
566
653
  /* @__PURE__ */ jsxRuntime.jsx(
567
- DeleteBtn$1,
654
+ DeleteBtn$2,
568
655
  {
569
656
  className: "delete-btn",
570
657
  onClick: (e) => {
@@ -583,7 +670,7 @@ function ConversationSidebar({
583
670
  ] })
584
671
  ] });
585
672
  }
586
- const PanelRoot = styled__default.default.div`
673
+ const PanelRoot$1 = styled__default.default.div`
587
674
  width: ${({ $open }) => $open ? "280px" : "0px"};
588
675
  min-width: ${({ $open }) => $open ? "280px" : "0px"};
589
676
  display: flex;
@@ -593,7 +680,7 @@ const PanelRoot = styled__default.default.div`
593
680
  overflow: hidden;
594
681
  transition: width 0.2s ease, min-width 0.2s ease;
595
682
  `;
596
- const PanelHeader = styled__default.default.div`
683
+ const PanelHeader$1 = styled__default.default.div`
597
684
  padding: 12px 16px;
598
685
  border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};
599
686
  `;
@@ -616,7 +703,7 @@ const MemoryContent = styled__default.default.div`
616
703
  flex: 1;
617
704
  min-width: 0;
618
705
  `;
619
- const CategoryBadge = styled__default.default.span`
706
+ const CategoryBadge$1 = styled__default.default.span`
620
707
  display: inline-block;
621
708
  font-size: 11px;
622
709
  padding: 1px 6px;
@@ -625,7 +712,7 @@ const CategoryBadge = styled__default.default.span`
625
712
  color: ${({ theme }) => theme.colors.neutral600};
626
713
  margin-bottom: 2px;
627
714
  `;
628
- const DeleteBtn = styled__default.default.button`
715
+ const DeleteBtn$1 = styled__default.default.button`
629
716
  opacity: 0;
630
717
  transition: opacity 0.15s;
631
718
  flex-shrink: 0;
@@ -653,8 +740,8 @@ const DeleteBtn = styled__default.default.button`
653
740
  }
654
741
  `;
655
742
  function MemoryPanel({ memories, open, onDelete }) {
656
- return /* @__PURE__ */ jsxRuntime.jsxs(PanelRoot, { $open: open, children: [
657
- /* @__PURE__ */ jsxRuntime.jsx(PanelHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: [
743
+ return /* @__PURE__ */ jsxRuntime.jsxs(PanelRoot$1, { $open: open, children: [
744
+ /* @__PURE__ */ jsxRuntime.jsx(PanelHeader$1, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: [
658
745
  "MEMORIES (",
659
746
  memories.length,
660
747
  ")"
@@ -662,11 +749,11 @@ function MemoryPanel({ memories, open, onDelete }) {
662
749
  /* @__PURE__ */ jsxRuntime.jsxs(MemoryList, { children: [
663
750
  memories.map((mem) => /* @__PURE__ */ jsxRuntime.jsxs(MemoryItem, { children: [
664
751
  /* @__PURE__ */ jsxRuntime.jsxs(MemoryContent, { children: [
665
- /* @__PURE__ */ jsxRuntime.jsx(CategoryBadge, { children: mem.category }),
752
+ /* @__PURE__ */ jsxRuntime.jsx(CategoryBadge$1, { children: mem.category }),
666
753
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral800", style: { display: "block" }, children: mem.content })
667
754
  ] }),
668
755
  /* @__PURE__ */ jsxRuntime.jsx(
669
- DeleteBtn,
756
+ DeleteBtn$1,
670
757
  {
671
758
  className: "memory-delete",
672
759
  onClick: () => onDelete(mem.documentId),
@@ -679,6 +766,255 @@ function MemoryPanel({ memories, open, onDelete }) {
679
766
  ] })
680
767
  ] });
681
768
  }
769
+ const PanelRoot = styled__default.default.div`
770
+ width: ${({ $open }) => $open ? "300px" : "0px"};
771
+ min-width: ${({ $open }) => $open ? "300px" : "0px"};
772
+ display: flex;
773
+ flex-direction: column;
774
+ border-left: ${({ $open, theme }) => $open ? `1px solid ${theme.colors.neutral200}` : "none"};
775
+ background: ${({ theme }) => theme.colors.neutral100};
776
+ overflow: hidden;
777
+ transition: width 0.2s ease, min-width 0.2s ease;
778
+ `;
779
+ const PanelHeader = styled__default.default.div`
780
+ padding: 12px 16px;
781
+ border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};
782
+ `;
783
+ const NoteList = styled__default.default.div`
784
+ flex: 1;
785
+ overflow-y: auto;
786
+ padding: 8px 0;
787
+ `;
788
+ const NoteItem = styled__default.default.div`
789
+ display: flex;
790
+ align-items: flex-start;
791
+ gap: 8px;
792
+ padding: 8px 16px;
793
+ cursor: pointer;
794
+ border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
795
+
796
+ &:hover {
797
+ background: ${({ theme }) => theme.colors.neutral150};
798
+ }
799
+
800
+ &:hover .note-delete {
801
+ opacity: 1;
802
+ }
803
+ `;
804
+ const NoteContent = styled__default.default.div`
805
+ flex: 1;
806
+ min-width: 0;
807
+ `;
808
+ const CategoryBadge = styled__default.default.span`
809
+ display: inline-block;
810
+ font-size: 11px;
811
+ padding: 1px 6px;
812
+ border-radius: 3px;
813
+ background: ${({ theme }) => theme.colors.neutral200};
814
+ color: ${({ theme }) => theme.colors.neutral600};
815
+ margin-bottom: 2px;
816
+ `;
817
+ const TagsBadge = styled__default.default.span`
818
+ display: inline-block;
819
+ font-size: 10px;
820
+ padding: 1px 5px;
821
+ border-radius: 3px;
822
+ background: ${({ theme }) => theme.colors.primary100};
823
+ color: ${({ theme }) => theme.colors.primary600};
824
+ margin-left: 4px;
825
+ `;
826
+ const DeleteBtn = styled__default.default.button`
827
+ opacity: 0;
828
+ transition: opacity 0.15s;
829
+ flex-shrink: 0;
830
+ display: flex;
831
+ align-items: center;
832
+ justify-content: center;
833
+ width: 22px;
834
+ height: 22px;
835
+ margin-top: 2px;
836
+ padding: 0;
837
+ border: none;
838
+ border-radius: 4px;
839
+ background: transparent;
840
+ color: ${({ theme }) => theme.colors.neutral500};
841
+ cursor: pointer;
842
+
843
+ &:hover {
844
+ background: ${({ theme }) => theme.colors.neutral300};
845
+ color: ${({ theme }) => theme.colors.danger600};
846
+ }
847
+
848
+ svg {
849
+ width: 12px;
850
+ height: 12px;
851
+ }
852
+ `;
853
+ const NoteTitle = styled__default.default(designSystem.Typography)`
854
+ display: block;
855
+ font-weight: 600;
856
+ margin-bottom: 2px;
857
+ `;
858
+ const NotePreview = styled__default.default(designSystem.Typography)`
859
+ display: -webkit-box;
860
+ -webkit-line-clamp: 2;
861
+ -webkit-box-orient: vertical;
862
+ overflow: hidden;
863
+ `;
864
+ const WideModalContent$3 = styled__default.default(designSystem.Modal.Content)`
865
+ max-width: 680px;
866
+ width: 100%;
867
+ `;
868
+ function EditNoteModal({ note, open, onClose, onSave }) {
869
+ const [title, setTitle] = react.useState("");
870
+ const [content, setContent] = react.useState("");
871
+ const [category, setCategory] = react.useState("research");
872
+ const [tags, setTags] = react.useState("");
873
+ const [source, setSource] = react.useState("");
874
+ react.useEffect(() => {
875
+ if (open && note) {
876
+ setTitle(note.title || "");
877
+ setContent(note.content);
878
+ setCategory(note.category);
879
+ setTags(note.tags || "");
880
+ setSource(note.source || "");
881
+ }
882
+ }, [open, note]);
883
+ const handleClose = () => {
884
+ onClose();
885
+ };
886
+ const handleSave = () => {
887
+ if (!note || !content.trim()) return;
888
+ onSave(note.documentId, { title, content, category, tags, source });
889
+ handleClose();
890
+ };
891
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent$3, { children: [
892
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: "Edit Note" }) }),
893
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 5, width: "100%", children: [
894
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
895
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Title" }),
896
+ /* @__PURE__ */ jsxRuntime.jsx(
897
+ designSystem.TextInput,
898
+ {
899
+ placeholder: "Short label for the note",
900
+ value: title,
901
+ onChange: (e) => setTitle(e.target.value)
902
+ }
903
+ )
904
+ ] }),
905
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
906
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Content" }),
907
+ /* @__PURE__ */ jsxRuntime.jsx(
908
+ designSystem.Textarea,
909
+ {
910
+ placeholder: "Note content (supports markdown)",
911
+ value: content,
912
+ onChange: (e) => setContent(e.target.value),
913
+ style: { width: "100%", minHeight: "160px", fontFamily: "monospace" }
914
+ }
915
+ )
916
+ ] }),
917
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, width: "100%", children: [
918
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { style: { flex: 1 }, children: [
919
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Category" }),
920
+ /* @__PURE__ */ jsxRuntime.jsxs(
921
+ designSystem.SingleSelect,
922
+ {
923
+ value: category,
924
+ onChange: (value) => setCategory(value),
925
+ children: [
926
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "research", children: "Research" }),
927
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "snippet", children: "Snippet" }),
928
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "idea", children: "Idea" }),
929
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "reference", children: "Reference" })
930
+ ]
931
+ }
932
+ )
933
+ ] }),
934
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { style: { flex: 1 }, children: [
935
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Source" }),
936
+ /* @__PURE__ */ jsxRuntime.jsx(
937
+ designSystem.TextInput,
938
+ {
939
+ placeholder: "e.g. conversation, URL",
940
+ value: source,
941
+ onChange: (e) => setSource(e.target.value)
942
+ }
943
+ )
944
+ ] })
945
+ ] }),
946
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
947
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Tags" }),
948
+ /* @__PURE__ */ jsxRuntime.jsx(
949
+ designSystem.TextInput,
950
+ {
951
+ placeholder: "Comma-separated tags",
952
+ value: tags,
953
+ onChange: (e) => setTags(e.target.value)
954
+ }
955
+ )
956
+ ] })
957
+ ] }) }),
958
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
959
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: "Cancel" }) }),
960
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleSave, disabled: !content.trim(), children: "Save changes" })
961
+ ] })
962
+ ] }) });
963
+ }
964
+ function NotePanel({ notes, open, onDelete, onEdit }) {
965
+ const [editingNote, setEditingNote] = react.useState(null);
966
+ const handleNoteClick = (note) => {
967
+ setEditingNote(note);
968
+ };
969
+ const handleCloseModal = () => {
970
+ setEditingNote(null);
971
+ };
972
+ const handleSave = (documentId, data) => {
973
+ onEdit(documentId, data);
974
+ setEditingNote(null);
975
+ };
976
+ return /* @__PURE__ */ jsxRuntime.jsxs(PanelRoot, { $open: open, children: [
977
+ /* @__PURE__ */ jsxRuntime.jsx(PanelHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: [
978
+ "NOTES (",
979
+ notes.length,
980
+ ")"
981
+ ] }) }),
982
+ /* @__PURE__ */ jsxRuntime.jsxs(NoteList, { children: [
983
+ notes.map((note) => /* @__PURE__ */ jsxRuntime.jsxs(NoteItem, { onClick: () => handleNoteClick(note), children: [
984
+ /* @__PURE__ */ jsxRuntime.jsxs(NoteContent, { children: [
985
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, wrap: "wrap", style: { marginBottom: 2 }, children: [
986
+ /* @__PURE__ */ jsxRuntime.jsx(CategoryBadge, { children: note.category }),
987
+ note.tags && note.tags.split(",").filter(Boolean).slice(0, 2).map((tag) => /* @__PURE__ */ jsxRuntime.jsx(TagsBadge, { children: tag.trim() }, tag.trim()))
988
+ ] }),
989
+ note.title && /* @__PURE__ */ jsxRuntime.jsx(NoteTitle, { variant: "omega", textColor: "neutral800", children: note.title }),
990
+ /* @__PURE__ */ jsxRuntime.jsx(NotePreview, { variant: "omega", textColor: "neutral600", children: note.content })
991
+ ] }),
992
+ /* @__PURE__ */ jsxRuntime.jsx(
993
+ DeleteBtn,
994
+ {
995
+ className: "note-delete",
996
+ onClick: (e) => {
997
+ e.stopPropagation();
998
+ onDelete(note.documentId);
999
+ },
1000
+ "aria-label": "Delete note",
1001
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {})
1002
+ }
1003
+ )
1004
+ ] }, note.documentId)),
1005
+ notes.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral500", children: "No notes saved yet. Save research notes, snippets, and ideas during conversations." }) })
1006
+ ] }),
1007
+ /* @__PURE__ */ jsxRuntime.jsx(
1008
+ EditNoteModal,
1009
+ {
1010
+ note: editingNote,
1011
+ open: editingNote !== null,
1012
+ onClose: handleCloseModal,
1013
+ onSave: handleSave
1014
+ }
1015
+ )
1016
+ ] });
1017
+ }
682
1018
  const Wrapper = styled__default.default.div`
683
1019
  position: relative;
684
1020
  `;
@@ -1105,14 +1441,14 @@ function extractContentLinks(toolCall) {
1105
1441
  }
1106
1442
  return links;
1107
1443
  }
1108
- if (toolCall.toolName === "writeContent") {
1444
+ if (toolCall.toolName === "createContent" || toolCall.toolName === "updateContent") {
1109
1445
  const doc = output.document;
1110
1446
  const docId = doc?.documentId;
1111
1447
  if (docId) {
1112
1448
  const title = doc?.title || doc?.name || docId;
1113
1449
  return [
1114
1450
  {
1115
- label: `${input.action === "create" ? "Created" : "Updated"}: ${title}`,
1451
+ label: `${toolCall.toolName === "createContent" ? "Created" : "Updated"}: ${title}`,
1116
1452
  to: buildContentManagerUrl(contentType, docId)
1117
1453
  }
1118
1454
  ];
@@ -1540,6 +1876,7 @@ function Chat() {
1540
1876
  const [input, setInput] = react.useState("");
1541
1877
  const [sidebarOpen, setSidebarOpen] = react.useState(false);
1542
1878
  const [memoryPanelOpen, setMemoryPanelOpen] = react.useState(false);
1879
+ const [notePanelOpen, setNotePanelOpen] = react.useState(false);
1543
1880
  const messagesEndRef = react.useRef(null);
1544
1881
  const prevIsLoadingRef = react.useRef(false);
1545
1882
  const {
@@ -1552,6 +1889,7 @@ function Chat() {
1552
1889
  removeConversation
1553
1890
  } = useConversations();
1554
1891
  const { memories, removeMemory, refresh: refreshMemories } = useMemories();
1892
+ const { notes, removeNote, editNote, refresh: refreshNotes } = useNotes();
1555
1893
  const { sources, enabledSources, enabledToolSources, toggleSource } = useToolSources();
1556
1894
  const { messages, sendMessage, isLoading, error } = useChat({
1557
1895
  initialMessages,
@@ -1562,9 +1900,10 @@ function Chat() {
1562
1900
  if (prevIsLoadingRef.current && !isLoading && messages.length > 0) {
1563
1901
  saveMessages(messages);
1564
1902
  refreshMemories();
1903
+ refreshNotes();
1565
1904
  }
1566
1905
  prevIsLoadingRef.current = isLoading;
1567
- }, [isLoading, messages, saveMessages, refreshMemories]);
1906
+ }, [isLoading, messages, saveMessages, refreshMemories, refreshNotes]);
1568
1907
  const handleSend = () => {
1569
1908
  if (!input.trim() || isLoading) return;
1570
1909
  sendMessage(input);
@@ -1606,6 +1945,18 @@ function Chat() {
1606
1945
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 4h12M2 8h12M2 12h8" }) })
1607
1946
  }
1608
1947
  ),
1948
+ /* @__PURE__ */ jsxRuntime.jsx(
1949
+ ToggleSidebarBtn,
1950
+ {
1951
+ onClick: () => navigate(`/plugins/${index.PLUGIN_ID}/note-store`),
1952
+ "aria-label": "Research Notes",
1953
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
1954
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 2v12h8V5l-3-3H4z" }),
1955
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 2v3h3" }),
1956
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 8h4M6 10.5h4" })
1957
+ ] })
1958
+ }
1959
+ ),
1609
1960
  /* @__PURE__ */ jsxRuntime.jsx(
1610
1961
  ToggleSidebarBtn,
1611
1962
  {
@@ -1639,6 +1990,18 @@ function Chat() {
1639
1990
  }
1640
1991
  ),
1641
1992
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1 } }),
1993
+ /* @__PURE__ */ jsxRuntime.jsx(
1994
+ ToggleSidebarBtn,
1995
+ {
1996
+ onClick: () => setNotePanelOpen((prev) => !prev),
1997
+ "aria-label": notePanelOpen ? "Hide notes" : "Show notes",
1998
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [
1999
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 2v12h8V5l-3-3H4z" }),
2000
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 2v3h3" }),
2001
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 8h4M6 10.5h4" })
2002
+ ] })
2003
+ }
2004
+ ),
1642
2005
  /* @__PURE__ */ jsxRuntime.jsx(
1643
2006
  ToggleSidebarBtn,
1644
2007
  {
@@ -1673,6 +2036,15 @@ function Chat() {
1673
2036
  }
1674
2037
  )
1675
2038
  ] }),
2039
+ /* @__PURE__ */ jsxRuntime.jsx(
2040
+ NotePanel,
2041
+ {
2042
+ notes,
2043
+ open: notePanelOpen,
2044
+ onDelete: removeNote,
2045
+ onEdit: editNote
2046
+ }
2047
+ ),
1676
2048
  /* @__PURE__ */ jsxRuntime.jsx(
1677
2049
  MemoryPanel,
1678
2050
  {
@@ -1695,8 +2067,8 @@ const HomePage = () => {
1695
2067
  /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(Chat, {}) })
1696
2068
  ] });
1697
2069
  };
1698
- const PAGE_SIZE$1 = 10;
1699
- const ActionBtn$1 = styled__default.default.button`
2070
+ const PAGE_SIZE$2 = 10;
2071
+ const ActionBtn$2 = styled__default.default.button`
1700
2072
  display: inline-flex;
1701
2073
  align-items: center;
1702
2074
  justify-content: center;
@@ -1719,16 +2091,16 @@ const ActionBtn$1 = styled__default.default.button`
1719
2091
  height: 16px;
1720
2092
  }
1721
2093
  `;
1722
- const DeleteActionBtn$1 = styled__default.default(ActionBtn$1)`
2094
+ const DeleteActionBtn$2 = styled__default.default(ActionBtn$2)`
1723
2095
  &:hover {
1724
2096
  color: ${({ theme }) => theme.colors.danger600};
1725
2097
  }
1726
2098
  `;
1727
- const WideModalContent$1 = styled__default.default(designSystem.Modal.Content)`
2099
+ const WideModalContent$2 = styled__default.default(designSystem.Modal.Content)`
1728
2100
  max-width: 680px;
1729
2101
  width: 100%;
1730
2102
  `;
1731
- function formatDate$1(iso) {
2103
+ function formatDate$2(iso) {
1732
2104
  return new Date(iso).toLocaleDateString(void 0, {
1733
2105
  year: "numeric",
1734
2106
  month: "short",
@@ -1760,7 +2132,7 @@ function MemoryModal({ memory, open, onClose, onSave }) {
1760
2132
  onSave({ content, category }, memory?.documentId);
1761
2133
  handleClose();
1762
2134
  };
1763
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent$1, { children: [
2135
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent$2, { children: [
1764
2136
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: isEdit ? "Edit Memory" : "Add Memory" }) }),
1765
2137
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 5, width: "100%", children: [
1766
2138
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
@@ -1813,8 +2185,8 @@ const MemoryStorePage = () => {
1813
2185
  (m) => m.content.toLowerCase().includes(q) || m.category.toLowerCase().includes(q)
1814
2186
  );
1815
2187
  }, [memories, search]);
1816
- const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$1));
1817
- const paginated = filtered.slice((page - 1) * PAGE_SIZE$1, page * PAGE_SIZE$1);
2188
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$2));
2189
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE$2, page * PAGE_SIZE$2);
1818
2190
  const handleOpenCreate = () => {
1819
2191
  setEditingMemory(null);
1820
2192
  setModalOpen(true);
@@ -1875,10 +2247,10 @@ const MemoryStorePage = () => {
1875
2247
  paginated.map((mem) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
1876
2248
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: mem.content }) }),
1877
2249
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: mem.category }) }),
1878
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatDate$1(mem.createdAt) }) }),
2250
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatDate$2(mem.createdAt) }) }),
1879
2251
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, children: [
1880
2252
  /* @__PURE__ */ jsxRuntime.jsx(
1881
- ActionBtn$1,
2253
+ ActionBtn$2,
1882
2254
  {
1883
2255
  onClick: () => handleOpenEdit(mem),
1884
2256
  "aria-label": "Edit memory",
@@ -1886,7 +2258,7 @@ const MemoryStorePage = () => {
1886
2258
  }
1887
2259
  ),
1888
2260
  /* @__PURE__ */ jsxRuntime.jsx(
1889
- DeleteActionBtn$1,
2261
+ DeleteActionBtn$2,
1890
2262
  {
1891
2263
  onClick: () => removeMemory(mem.documentId),
1892
2264
  "aria-label": "Delete memory",
@@ -1986,8 +2358,8 @@ function usePublicMemories() {
1986
2358
  }, []);
1987
2359
  return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
1988
2360
  }
1989
- const PAGE_SIZE = 10;
1990
- const ActionBtn = styled__default.default.button`
2361
+ const PAGE_SIZE$1 = 10;
2362
+ const ActionBtn$1 = styled__default.default.button`
1991
2363
  display: inline-flex;
1992
2364
  align-items: center;
1993
2365
  justify-content: center;
@@ -2010,16 +2382,16 @@ const ActionBtn = styled__default.default.button`
2010
2382
  height: 16px;
2011
2383
  }
2012
2384
  `;
2013
- const DeleteActionBtn = styled__default.default(ActionBtn)`
2385
+ const DeleteActionBtn$1 = styled__default.default(ActionBtn$1)`
2014
2386
  &:hover {
2015
2387
  color: ${({ theme }) => theme.colors.danger600};
2016
2388
  }
2017
2389
  `;
2018
- const WideModalContent = styled__default.default(designSystem.Modal.Content)`
2390
+ const WideModalContent$1 = styled__default.default(designSystem.Modal.Content)`
2019
2391
  max-width: 680px;
2020
2392
  width: 100%;
2021
2393
  `;
2022
- function formatDate(iso) {
2394
+ function formatDate$1(iso) {
2023
2395
  return new Date(iso).toLocaleDateString(void 0, {
2024
2396
  year: "numeric",
2025
2397
  month: "short",
@@ -2051,7 +2423,7 @@ function PublicMemoryModal({ memory, open, onClose, onSave }) {
2051
2423
  onSave({ content, category }, memory?.documentId);
2052
2424
  handleClose();
2053
2425
  };
2054
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent, { children: [
2426
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent$1, { children: [
2055
2427
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: isEdit ? "Edit Public Memory" : "Add Public Memory" }) }),
2056
2428
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 5, width: "100%", children: [
2057
2429
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
@@ -2104,8 +2476,8 @@ const PublicMemoryStorePage = () => {
2104
2476
  (m) => m.content.toLowerCase().includes(q) || m.category.toLowerCase().includes(q)
2105
2477
  );
2106
2478
  }, [memories, search]);
2107
- const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2108
- const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2479
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE$1));
2480
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE$1, page * PAGE_SIZE$1);
2109
2481
  const handleOpenCreate = () => {
2110
2482
  setEditingMemory(null);
2111
2483
  setModalOpen(true);
@@ -2166,10 +2538,10 @@ const PublicMemoryStorePage = () => {
2166
2538
  paginated.map((mem) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
2167
2539
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: mem.content }) }),
2168
2540
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: mem.category }) }),
2169
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatDate(mem.createdAt) }) }),
2541
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatDate$1(mem.createdAt) }) }),
2170
2542
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, children: [
2171
2543
  /* @__PURE__ */ jsxRuntime.jsx(
2172
- ActionBtn,
2544
+ ActionBtn$1,
2173
2545
  {
2174
2546
  onClick: () => handleOpenEdit(mem),
2175
2547
  "aria-label": "Edit memory",
@@ -2177,7 +2549,7 @@ const PublicMemoryStorePage = () => {
2177
2549
  }
2178
2550
  ),
2179
2551
  /* @__PURE__ */ jsxRuntime.jsx(
2180
- DeleteActionBtn,
2552
+ DeleteActionBtn$1,
2181
2553
  {
2182
2554
  onClick: () => removeMemory(mem.documentId),
2183
2555
  "aria-label": "Delete memory",
@@ -2201,6 +2573,292 @@ const PublicMemoryStorePage = () => {
2201
2573
  ] })
2202
2574
  ] });
2203
2575
  };
2576
+ const PAGE_SIZE = 10;
2577
+ const ActionBtn = styled__default.default.button`
2578
+ display: inline-flex;
2579
+ align-items: center;
2580
+ justify-content: center;
2581
+ width: 32px;
2582
+ height: 32px;
2583
+ padding: 0;
2584
+ border: none;
2585
+ border-radius: 4px;
2586
+ background: transparent;
2587
+ color: ${({ theme }) => theme.colors.neutral600};
2588
+ cursor: pointer;
2589
+
2590
+ &:hover {
2591
+ background: ${({ theme }) => theme.colors.neutral200};
2592
+ color: ${({ theme }) => theme.colors.primary600};
2593
+ }
2594
+
2595
+ svg {
2596
+ width: 16px;
2597
+ height: 16px;
2598
+ }
2599
+ `;
2600
+ const DeleteActionBtn = styled__default.default(ActionBtn)`
2601
+ &:hover {
2602
+ color: ${({ theme }) => theme.colors.danger600};
2603
+ }
2604
+ `;
2605
+ const WideModalContent = styled__default.default(designSystem.Modal.Content)`
2606
+ max-width: 680px;
2607
+ width: 100%;
2608
+ `;
2609
+ function formatDate(iso) {
2610
+ return new Date(iso).toLocaleDateString(void 0, {
2611
+ year: "numeric",
2612
+ month: "short",
2613
+ day: "numeric",
2614
+ hour: "2-digit",
2615
+ minute: "2-digit"
2616
+ });
2617
+ }
2618
+ function NoteModal({ note, open, onClose, onSave }) {
2619
+ const [title, setTitle] = react.useState("");
2620
+ const [content, setContent] = react.useState("");
2621
+ const [category, setCategory] = react.useState("research");
2622
+ const [tags, setTags] = react.useState("");
2623
+ const [source, setSource] = react.useState("");
2624
+ const isEdit = note !== null;
2625
+ react.useEffect(() => {
2626
+ if (open && note) {
2627
+ setTitle(note.title || "");
2628
+ setContent(note.content);
2629
+ setCategory(note.category);
2630
+ setTags(note.tags || "");
2631
+ setSource(note.source || "");
2632
+ } else if (open) {
2633
+ setTitle("");
2634
+ setContent("");
2635
+ setCategory("research");
2636
+ setTags("");
2637
+ setSource("");
2638
+ }
2639
+ }, [open, note]);
2640
+ const handleClose = () => {
2641
+ setTitle("");
2642
+ setContent("");
2643
+ setCategory("research");
2644
+ setTags("");
2645
+ setSource("");
2646
+ onClose();
2647
+ };
2648
+ const handleSave = () => {
2649
+ if (!content.trim()) return;
2650
+ onSave({ title, content, category, tags, source }, note?.documentId);
2651
+ handleClose();
2652
+ };
2653
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(WideModalContent, { children: [
2654
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: isEdit ? "Edit Note" : "Add Note" }) }),
2655
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 5, width: "100%", children: [
2656
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
2657
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Title" }),
2658
+ /* @__PURE__ */ jsxRuntime.jsx(
2659
+ designSystem.TextInput,
2660
+ {
2661
+ placeholder: "Short label for the note",
2662
+ value: title,
2663
+ onChange: (e) => setTitle(e.target.value)
2664
+ }
2665
+ )
2666
+ ] }),
2667
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
2668
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Content" }),
2669
+ /* @__PURE__ */ jsxRuntime.jsx(
2670
+ designSystem.Textarea,
2671
+ {
2672
+ placeholder: "Note content (supports markdown)",
2673
+ value: content,
2674
+ onChange: (e) => setContent(e.target.value),
2675
+ style: { width: "100%", minHeight: "160px", maxHeight: "300px", overflow: "auto", fontFamily: "monospace" }
2676
+ }
2677
+ )
2678
+ ] }),
2679
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, width: "100%", children: [
2680
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { style: { flex: 1 }, children: [
2681
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Category" }),
2682
+ /* @__PURE__ */ jsxRuntime.jsxs(
2683
+ designSystem.SingleSelect,
2684
+ {
2685
+ value: category,
2686
+ onChange: (value) => setCategory(value),
2687
+ children: [
2688
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "research", children: "Research" }),
2689
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "snippet", children: "Snippet" }),
2690
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "idea", children: "Idea" }),
2691
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "reference", children: "Reference" })
2692
+ ]
2693
+ }
2694
+ )
2695
+ ] }),
2696
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { style: { flex: 1 }, children: [
2697
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Source" }),
2698
+ /* @__PURE__ */ jsxRuntime.jsx(
2699
+ designSystem.TextInput,
2700
+ {
2701
+ placeholder: "e.g. conversation, URL",
2702
+ value: source,
2703
+ onChange: (e) => setSource(e.target.value)
2704
+ }
2705
+ )
2706
+ ] })
2707
+ ] }),
2708
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
2709
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Tags" }),
2710
+ /* @__PURE__ */ jsxRuntime.jsx(
2711
+ designSystem.TextInput,
2712
+ {
2713
+ placeholder: "Comma-separated tags (e.g. strapi, api, tutorial)",
2714
+ value: tags,
2715
+ onChange: (e) => setTags(e.target.value)
2716
+ }
2717
+ ),
2718
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, { children: "Used to filter and organize notes" })
2719
+ ] })
2720
+ ] }) }),
2721
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
2722
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: "Cancel" }) }),
2723
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleSave, disabled: !content.trim(), children: isEdit ? "Save changes" : "Add note" })
2724
+ ] })
2725
+ ] }) });
2726
+ }
2727
+ const NoteStorePage = () => {
2728
+ const navigate = reactRouterDom.useNavigate();
2729
+ const { notes, loading, addNote, editNote, removeNote, clearAll } = useNotes();
2730
+ const [search, setSearch] = react.useState("");
2731
+ const [page, setPage] = react.useState(1);
2732
+ const [modalOpen, setModalOpen] = react.useState(false);
2733
+ const [editingNote, setEditingNote] = react.useState(null);
2734
+ const [clearDialogOpen, setClearDialogOpen] = react.useState(false);
2735
+ const filtered = react.useMemo(() => {
2736
+ if (!search.trim()) return notes;
2737
+ const q = search.toLowerCase();
2738
+ return notes.filter(
2739
+ (n) => (n.title || "").toLowerCase().includes(q) || n.content.toLowerCase().includes(q) || n.category.toLowerCase().includes(q) || (n.tags || "").toLowerCase().includes(q)
2740
+ );
2741
+ }, [notes, search]);
2742
+ const pageCount = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2743
+ const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2744
+ const handleOpenCreate = () => {
2745
+ setEditingNote(null);
2746
+ setModalOpen(true);
2747
+ };
2748
+ const handleOpenEdit = (note) => {
2749
+ setEditingNote(note);
2750
+ setModalOpen(true);
2751
+ };
2752
+ const handleCloseModal = () => {
2753
+ setModalOpen(false);
2754
+ setEditingNote(null);
2755
+ };
2756
+ const handleSave = (data, documentId) => {
2757
+ if (documentId) {
2758
+ editNote(documentId, data);
2759
+ } else {
2760
+ addNote(data);
2761
+ }
2762
+ };
2763
+ const handleClearAll = () => {
2764
+ clearAll();
2765
+ setClearDialogOpen(false);
2766
+ };
2767
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
2768
+ /* @__PURE__ */ jsxRuntime.jsx(
2769
+ admin.Layouts.Header,
2770
+ {
2771
+ title: "Research Notes",
2772
+ subtitle: `${notes.length} notes saved`,
2773
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2774
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger-light", onClick: () => setClearDialogOpen(true), disabled: notes.length === 0, children: "Clear all" }),
2775
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: handleOpenCreate, children: "Add note" })
2776
+ ] }),
2777
+ navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "ghost", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), onClick: () => navigate(`/plugins/${index.PLUGIN_ID}`), children: "Back to Chat" })
2778
+ }
2779
+ ),
2780
+ /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Content, { children: [
2781
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.SearchForm, { children: /* @__PURE__ */ jsxRuntime.jsx(
2782
+ designSystem.Searchbar,
2783
+ {
2784
+ name: "search",
2785
+ value: search,
2786
+ onChange: (e) => {
2787
+ setSearch(e.target.value);
2788
+ setPage(1);
2789
+ },
2790
+ onClear: () => {
2791
+ setSearch("");
2792
+ setPage(1);
2793
+ },
2794
+ placeholder: "Search notes...",
2795
+ children: "Search"
2796
+ }
2797
+ ) }) }),
2798
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 6, rowCount: paginated.length + 1, children: [
2799
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
2800
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Title" }) }),
2801
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Content" }) }),
2802
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Category" }) }),
2803
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Tags" }) }),
2804
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Created" }) }),
2805
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Actions" }) })
2806
+ ] }) }),
2807
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tbody, { children: [
2808
+ loading && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: "Loading..." }) }) }) }),
2809
+ !loading && paginated.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral500", children: search ? "No notes match your search" : "No notes saved yet. Save research notes, snippets, and ideas during conversations." }) }) }) }),
2810
+ paginated.map((note) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
2811
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", fontWeight: "semiBold", children: note.title || "—" }) }),
2812
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", ellipsis: true, children: note.content.length > 100 ? `${note.content.slice(0, 100)}...` : note.content }) }),
2813
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: note.category }) }),
2814
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: note.tags || "—" }) }),
2815
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatDate(note.createdAt) }) }),
2816
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, children: [
2817
+ /* @__PURE__ */ jsxRuntime.jsx(
2818
+ ActionBtn,
2819
+ {
2820
+ onClick: () => handleOpenEdit(note),
2821
+ "aria-label": "Edit note",
2822
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {})
2823
+ }
2824
+ ),
2825
+ /* @__PURE__ */ jsxRuntime.jsx(
2826
+ DeleteActionBtn,
2827
+ {
2828
+ onClick: () => removeNote(note.documentId),
2829
+ "aria-label": "Delete note",
2830
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {})
2831
+ }
2832
+ )
2833
+ ] }) })
2834
+ ] }, note.documentId))
2835
+ ] })
2836
+ ] }),
2837
+ pageCount > 1 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Pagination.Root, { pageCount, activePage: page, onPageChange: setPage, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Pagination.Links, {}) }) }) }),
2838
+ /* @__PURE__ */ jsxRuntime.jsx(
2839
+ NoteModal,
2840
+ {
2841
+ note: editingNote,
2842
+ open: modalOpen,
2843
+ onClose: handleCloseModal,
2844
+ onSave: handleSave
2845
+ }
2846
+ ),
2847
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: clearDialogOpen, onOpenChange: setClearDialogOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2848
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: "Clear all notes" }),
2849
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Body, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, {}), children: [
2850
+ "Are you sure you want to delete all ",
2851
+ notes.length,
2852
+ " notes? This action cannot be undone."
2853
+ ] }),
2854
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2855
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: "Cancel" }) }),
2856
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Action, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger", onClick: handleClearAll, children: "Clear all" }) })
2857
+ ] })
2858
+ ] }) })
2859
+ ] })
2860
+ ] });
2861
+ };
2204
2862
  function getStrapiOrigin() {
2205
2863
  return globalThis.location.origin;
2206
2864
  }
@@ -2350,6 +3008,7 @@ const App = () => {
2350
3008
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }),
2351
3009
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "memory-store", element: /* @__PURE__ */ jsxRuntime.jsx(MemoryStorePage, {}) }),
2352
3010
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "public-memory-store", element: /* @__PURE__ */ jsxRuntime.jsx(PublicMemoryStorePage, {}) }),
3011
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "note-store", element: /* @__PURE__ */ jsxRuntime.jsx(NoteStorePage, {}) }),
2353
3012
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "widget-preview", element: /* @__PURE__ */ jsxRuntime.jsx(WidgetPreviewPage, {}) }),
2354
3013
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
2355
3014
  ] });