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.
- package/dist/_chunks/{App-joEmdpxi.js → App-DTbAnq7K.js} +710 -51
- package/dist/_chunks/{App-DMdQymB3.mjs → App-DZVBmpvs.mjs} +712 -53
- package/dist/_chunks/{index-B7qLITWV.js → index-C3xn2IND.js} +1 -1
- package/dist/_chunks/{index-DrLcqX__.mjs → index-Ca2F2wBp.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/NotePanel.d.ts +15 -0
- package/dist/admin/src/hooks/useNotes.d.ts +22 -0
- package/dist/admin/src/pages/NoteStorePage.d.ts +2 -0
- package/dist/admin/src/utils/notes-api.d.ts +28 -0
- package/dist/server/index.js +536 -121
- package/dist/server/index.mjs +536 -121
- package/dist/server/src/content-types/index.d.ts +46 -0
- package/dist/server/src/content-types/note/index.d.ts +47 -0
- package/dist/server/src/controllers/index.d.ts +9 -0
- package/dist/server/src/controllers/note.d.ts +12 -0
- package/dist/server/src/index.d.ts +55 -0
- package/dist/server/src/lib/trim-messages.d.ts +11 -0
- package/dist/server/src/mcp/resources/tool-guide.d.ts +5 -0
- package/dist/server/src/tool-logic/aggregate-content.d.ts +1 -1
- package/dist/server/src/tool-logic/create-content.d.ts +1 -1
- package/dist/server/src/tool-logic/find-one-content.d.ts +1 -1
- package/dist/server/src/tool-logic/index.d.ts +4 -0
- package/dist/server/src/tool-logic/list-content-types.d.ts +1 -1
- package/dist/server/src/tool-logic/manage-task.d.ts +1 -1
- package/dist/server/src/tool-logic/recall-notes.d.ts +22 -0
- package/dist/server/src/tool-logic/save-note.d.ts +17 -0
- package/dist/server/src/tool-logic/update-content.d.ts +1 -1
- package/dist/server/src/tool-logic/upload-media.d.ts +1 -1
- package/dist/server/src/tools/definitions/recall-notes.d.ts +2 -0
- package/dist/server/src/tools/definitions/save-note.d.ts +2 -0
- 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,
|
|
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-
|
|
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$
|
|
209
|
-
function headers$
|
|
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$
|
|
217
|
-
const res = await fetch(url, { headers: headers$
|
|
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$
|
|
223
|
+
return request$3(BASE$3());
|
|
224
224
|
}
|
|
225
225
|
function fetchConversation(documentId) {
|
|
226
|
-
return request$
|
|
226
|
+
return request$3(`${BASE$3()}/${documentId}`);
|
|
227
227
|
}
|
|
228
228
|
function createConversation(data) {
|
|
229
|
-
return request$
|
|
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$
|
|
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$
|
|
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$
|
|
330
|
-
function headers$
|
|
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$
|
|
338
|
-
const res = await fetch(url, { headers: headers$
|
|
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$
|
|
344
|
+
return request$2(BASE$2());
|
|
345
345
|
}
|
|
346
346
|
function createMemory(data) {
|
|
347
|
-
return request$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
1693
|
-
const ActionBtn$
|
|
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$
|
|
2088
|
+
const DeleteActionBtn$2 = styled(ActionBtn$2)`
|
|
1717
2089
|
&:hover {
|
|
1718
2090
|
color: ${({ theme }) => theme.colors.danger600};
|
|
1719
2091
|
}
|
|
1720
2092
|
`;
|
|
1721
|
-
const WideModalContent$
|
|
2093
|
+
const WideModalContent$2 = styled(Modal.Content)`
|
|
1722
2094
|
max-width: 680px;
|
|
1723
2095
|
width: 100%;
|
|
1724
2096
|
`;
|
|
1725
|
-
function formatDate$
|
|
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$
|
|
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$
|
|
1811
|
-
const paginated = filtered.slice((page - 1) * PAGE_SIZE$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
] });
|