strapi-plugin-ai-sdk 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{App-BGIUzHMh.js → App-DcU3uMiY.js} +198 -5
- package/dist/_chunks/{App-v0CobEGM.mjs → App-Dwx6guC-.mjs} +200 -7
- package/dist/_chunks/{index-BNk29VRc.js → index-D0dDUeEO.js} +1 -1
- package/dist/_chunks/{index-CFO5UshL.mjs → index-skxI4tiW.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/ToolSourcePicker.d.ts +8 -0
- package/dist/admin/src/hooks/useChat.d.ts +1 -0
- package/dist/admin/src/hooks/useToolSources.d.ts +13 -0
- package/dist/server/index.js +58 -4
- package/dist/server/index.mjs +58 -4
- package/dist/server/src/controllers/controller.d.ts +1 -0
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/index.d.ts +4 -2
- package/dist/server/src/lib/tool-registry.d.ts +8 -0
- package/dist/server/src/lib/utils.d.ts +1 -0
- package/dist/server/src/routes/admin/index.d.ts +2 -2
- package/dist/server/src/routes/index.d.ts +2 -2
- package/dist/server/src/services/index.d.ts +1 -0
- package/dist/server/src/services/service.d.ts +1 -0
- package/package.json +1 -1
|
@@ -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-
|
|
9
|
+
const index = require("./index-D0dDUeEO.js");
|
|
10
10
|
const icons = require("@strapi/icons");
|
|
11
11
|
const Markdown = require("react-markdown");
|
|
12
12
|
const remarkGfm = require("remark-gfm");
|
|
@@ -107,15 +107,17 @@ function toUIMessages(messages) {
|
|
|
107
107
|
parts: [{ type: "text", text: message.content }]
|
|
108
108
|
}));
|
|
109
109
|
}
|
|
110
|
-
async function fetchChatStream(messages) {
|
|
110
|
+
async function fetchChatStream(messages, enabledToolSources) {
|
|
111
111
|
const token = getToken();
|
|
112
|
+
const body = { messages: toUIMessages(messages) };
|
|
113
|
+
if (enabledToolSources) body.enabledToolSources = enabledToolSources;
|
|
112
114
|
const response = await fetch(`${getBackendURL()}/${index.PLUGIN_ID}/chat`, {
|
|
113
115
|
method: "POST",
|
|
114
116
|
headers: {
|
|
115
117
|
"Content-Type": "application/json",
|
|
116
118
|
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
117
119
|
},
|
|
118
|
-
body: JSON.stringify(
|
|
120
|
+
body: JSON.stringify(body)
|
|
119
121
|
});
|
|
120
122
|
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
|
|
121
123
|
const reader = response.body?.getReader();
|
|
@@ -160,7 +162,7 @@ function useChat(options) {
|
|
|
160
162
|
setIsLoading(true);
|
|
161
163
|
setError(null);
|
|
162
164
|
try {
|
|
163
|
-
const reader = await fetchChatStream([...messages, userMessage]);
|
|
165
|
+
const reader = await fetchChatStream([...messages, userMessage], options?.enabledToolSources);
|
|
164
166
|
let streamStarted = false;
|
|
165
167
|
const result = await readSSEStream(reader, {
|
|
166
168
|
onTextDelta: (content) => {
|
|
@@ -392,6 +394,51 @@ function useMemories() {
|
|
|
392
394
|
}, []);
|
|
393
395
|
return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
|
|
394
396
|
}
|
|
397
|
+
const STORAGE_KEY = `${index.PLUGIN_ID}:enabledToolSources`;
|
|
398
|
+
function useToolSources() {
|
|
399
|
+
const [sources, setSources] = react.useState([]);
|
|
400
|
+
const [enabledSources, setEnabledSources] = react.useState(() => {
|
|
401
|
+
try {
|
|
402
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
403
|
+
if (stored) return new Set(JSON.parse(stored));
|
|
404
|
+
} catch {
|
|
405
|
+
}
|
|
406
|
+
return /* @__PURE__ */ new Set();
|
|
407
|
+
});
|
|
408
|
+
const [loaded, setLoaded] = react.useState(false);
|
|
409
|
+
react.useEffect(() => {
|
|
410
|
+
const token = getToken();
|
|
411
|
+
fetch(`${getBackendURL()}/${index.PLUGIN_ID}/tool-sources`, {
|
|
412
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
413
|
+
}).then((res) => res.json()).then((json) => {
|
|
414
|
+
const data = json.data ?? [];
|
|
415
|
+
setSources(data);
|
|
416
|
+
setEnabledSources((prev) => {
|
|
417
|
+
if (prev.size === 0) {
|
|
418
|
+
const all = new Set(data.filter((s) => s.id !== "built-in").map((s) => s.id));
|
|
419
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify([...all]));
|
|
420
|
+
return all;
|
|
421
|
+
}
|
|
422
|
+
return prev;
|
|
423
|
+
});
|
|
424
|
+
setLoaded(true);
|
|
425
|
+
}).catch(() => setLoaded(true));
|
|
426
|
+
}, []);
|
|
427
|
+
const toggleSource = react.useCallback((id) => {
|
|
428
|
+
setEnabledSources((prev) => {
|
|
429
|
+
const next = new Set(prev);
|
|
430
|
+
if (next.has(id)) next.delete(id);
|
|
431
|
+
else next.add(id);
|
|
432
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify([...next]));
|
|
433
|
+
return next;
|
|
434
|
+
});
|
|
435
|
+
}, []);
|
|
436
|
+
const enabledToolSources = react.useMemo(
|
|
437
|
+
() => loaded ? [...enabledSources] : void 0,
|
|
438
|
+
[enabledSources, loaded]
|
|
439
|
+
);
|
|
440
|
+
return { sources, enabledSources, enabledToolSources, toggleSource, loaded };
|
|
441
|
+
}
|
|
395
442
|
const SidebarRoot = styled__default.default.div`
|
|
396
443
|
width: ${({ $open }) => $open ? "260px" : "0px"};
|
|
397
444
|
min-width: ${({ $open }) => $open ? "260px" : "0px"};
|
|
@@ -618,6 +665,142 @@ function MemoryPanel({ memories, open, onDelete }) {
|
|
|
618
665
|
] })
|
|
619
666
|
] });
|
|
620
667
|
}
|
|
668
|
+
const Wrapper = styled__default.default.div`
|
|
669
|
+
position: relative;
|
|
670
|
+
`;
|
|
671
|
+
const IconBtn = styled__default.default.button`
|
|
672
|
+
display: flex;
|
|
673
|
+
align-items: center;
|
|
674
|
+
justify-content: center;
|
|
675
|
+
width: 32px;
|
|
676
|
+
height: 32px;
|
|
677
|
+
border: 1px solid #dcdce4;
|
|
678
|
+
border-radius: 4px;
|
|
679
|
+
background: #ffffff;
|
|
680
|
+
color: #666687;
|
|
681
|
+
cursor: pointer;
|
|
682
|
+
flex-shrink: 0;
|
|
683
|
+
|
|
684
|
+
&:hover {
|
|
685
|
+
background: #f0f0f5;
|
|
686
|
+
color: #4945ff;
|
|
687
|
+
border-color: #4945ff;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
svg {
|
|
691
|
+
width: 16px;
|
|
692
|
+
height: 16px;
|
|
693
|
+
}
|
|
694
|
+
`;
|
|
695
|
+
const Popover = styled__default.default.div`
|
|
696
|
+
position: absolute;
|
|
697
|
+
top: 40px;
|
|
698
|
+
left: 0;
|
|
699
|
+
z-index: 10;
|
|
700
|
+
width: 240px;
|
|
701
|
+
max-height: 360px;
|
|
702
|
+
overflow-y: auto;
|
|
703
|
+
background: #ffffff;
|
|
704
|
+
border: 1px solid #dcdce4;
|
|
705
|
+
border-radius: 4px;
|
|
706
|
+
box-shadow: 0 2px 12px rgba(33, 33, 52, 0.12);
|
|
707
|
+
padding: 8px 0;
|
|
708
|
+
`;
|
|
709
|
+
const SourceRow = styled__default.default.label`
|
|
710
|
+
display: flex;
|
|
711
|
+
flex-direction: column;
|
|
712
|
+
padding: 6px 12px;
|
|
713
|
+
cursor: pointer;
|
|
714
|
+
font-size: 13px;
|
|
715
|
+
color: #32324d;
|
|
716
|
+
|
|
717
|
+
&:hover {
|
|
718
|
+
background: #f6f6f9;
|
|
719
|
+
}
|
|
720
|
+
`;
|
|
721
|
+
const SourceMain = styled__default.default.div`
|
|
722
|
+
display: flex;
|
|
723
|
+
flex-direction: row;
|
|
724
|
+
align-items: center;
|
|
725
|
+
gap: 8px;
|
|
726
|
+
`;
|
|
727
|
+
const Badge = styled__default.default.div`
|
|
728
|
+
font-size: 11px;
|
|
729
|
+
color: #a5a5ba;
|
|
730
|
+
margin-left: 24px;
|
|
731
|
+
margin-top: 1px;
|
|
732
|
+
`;
|
|
733
|
+
const Toggle = styled__default.default.input`
|
|
734
|
+
accent-color: #4945ff;
|
|
735
|
+
flex-shrink: 0;
|
|
736
|
+
width: 16px;
|
|
737
|
+
height: 16px;
|
|
738
|
+
margin: 0;
|
|
739
|
+
`;
|
|
740
|
+
const Header = styled__default.default.div`
|
|
741
|
+
padding: 6px 12px 4px;
|
|
742
|
+
font-size: 11px;
|
|
743
|
+
font-weight: 600;
|
|
744
|
+
color: #a5a5ba;
|
|
745
|
+
text-transform: uppercase;
|
|
746
|
+
letter-spacing: 0.5px;
|
|
747
|
+
`;
|
|
748
|
+
function ToolSourcePicker({ sources, enabledSources, onToggle }) {
|
|
749
|
+
const [open, setOpen] = react.useState(false);
|
|
750
|
+
const ref = react.useRef(null);
|
|
751
|
+
react.useEffect(() => {
|
|
752
|
+
if (!open) return;
|
|
753
|
+
function handleClick(e) {
|
|
754
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
755
|
+
}
|
|
756
|
+
document.addEventListener("mousedown", handleClick);
|
|
757
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
758
|
+
}, [open]);
|
|
759
|
+
const builtIn = sources.find((s) => s.id === "built-in");
|
|
760
|
+
const plugins = sources.filter((s) => s.id !== "built-in");
|
|
761
|
+
if (sources.length === 0) return null;
|
|
762
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { ref, children: [
|
|
763
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconBtn, { onClick: () => setOpen((p) => !p), "aria-label": "Tool sources", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
764
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.5 2.5L13 6l-7 7H2.5v-3.5l7-7z" }),
|
|
765
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4l4 4" })
|
|
766
|
+
] }) }),
|
|
767
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
768
|
+
builtIn && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
769
|
+
/* @__PURE__ */ jsxRuntime.jsx(Header, { children: "Built-in" }),
|
|
770
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SourceRow, { children: [
|
|
771
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SourceMain, { children: [
|
|
772
|
+
/* @__PURE__ */ jsxRuntime.jsx(Toggle, { type: "checkbox", checked: true, disabled: true }),
|
|
773
|
+
builtIn.label
|
|
774
|
+
] }),
|
|
775
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { children: [
|
|
776
|
+
builtIn.toolCount,
|
|
777
|
+
" tools"
|
|
778
|
+
] })
|
|
779
|
+
] })
|
|
780
|
+
] }),
|
|
781
|
+
plugins.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
782
|
+
/* @__PURE__ */ jsxRuntime.jsx(Header, { children: "Plugins" }),
|
|
783
|
+
plugins.map((s) => /* @__PURE__ */ jsxRuntime.jsxs(SourceRow, { children: [
|
|
784
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SourceMain, { children: [
|
|
785
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
786
|
+
Toggle,
|
|
787
|
+
{
|
|
788
|
+
type: "checkbox",
|
|
789
|
+
checked: enabledSources.has(s.id),
|
|
790
|
+
onChange: () => onToggle(s.id)
|
|
791
|
+
}
|
|
792
|
+
),
|
|
793
|
+
s.label
|
|
794
|
+
] }),
|
|
795
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { children: [
|
|
796
|
+
s.toolCount,
|
|
797
|
+
" tools"
|
|
798
|
+
] })
|
|
799
|
+
] }, s.id))
|
|
800
|
+
] })
|
|
801
|
+
] })
|
|
802
|
+
] });
|
|
803
|
+
}
|
|
621
804
|
const SCORE_LABELS = {
|
|
622
805
|
1: "Negligible",
|
|
623
806
|
2: "Minor",
|
|
@@ -1355,9 +1538,11 @@ function Chat() {
|
|
|
1355
1538
|
removeConversation
|
|
1356
1539
|
} = useConversations();
|
|
1357
1540
|
const { memories, removeMemory, refresh: refreshMemories } = useMemories();
|
|
1541
|
+
const { sources, enabledSources, enabledToolSources, toggleSource } = useToolSources();
|
|
1358
1542
|
const { messages, sendMessage, isLoading, error } = useChat({
|
|
1359
1543
|
initialMessages,
|
|
1360
|
-
conversationId: activeId
|
|
1544
|
+
conversationId: activeId,
|
|
1545
|
+
enabledToolSources
|
|
1361
1546
|
});
|
|
1362
1547
|
react.useEffect(() => {
|
|
1363
1548
|
if (prevIsLoadingRef.current && !isLoading && messages.length > 0) {
|
|
@@ -1431,6 +1616,14 @@ function Chat() {
|
|
|
1431
1616
|
] })
|
|
1432
1617
|
}
|
|
1433
1618
|
),
|
|
1619
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1620
|
+
ToolSourcePicker,
|
|
1621
|
+
{
|
|
1622
|
+
sources,
|
|
1623
|
+
enabledSources,
|
|
1624
|
+
onToggle: toggleSource
|
|
1625
|
+
}
|
|
1626
|
+
),
|
|
1434
1627
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1 } }),
|
|
1435
1628
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1436
1629
|
ToggleSidebarBtn,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
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
4
|
import { Box, Typography, TextInput, Button, Main, SearchForm, Searchbar, Table, Thead, Tr, Th, Tbody, Td, Flex, Pagination, Modal, Field, Textarea, SingleSelect, SingleSelectOption } from "@strapi/design-system";
|
|
5
|
-
import { useState, useEffect, useCallback,
|
|
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-
|
|
7
|
+
import { P as PLUGIN_ID } from "./index-skxI4tiW.mjs";
|
|
8
8
|
import { Plus, Trash, Sparkle, ArrowLeft, Pencil } from "@strapi/icons";
|
|
9
9
|
import Markdown from "react-markdown";
|
|
10
10
|
import remarkGfm from "remark-gfm";
|
|
@@ -101,15 +101,17 @@ function toUIMessages(messages) {
|
|
|
101
101
|
parts: [{ type: "text", text: message.content }]
|
|
102
102
|
}));
|
|
103
103
|
}
|
|
104
|
-
async function fetchChatStream(messages) {
|
|
104
|
+
async function fetchChatStream(messages, enabledToolSources) {
|
|
105
105
|
const token = getToken();
|
|
106
|
+
const body = { messages: toUIMessages(messages) };
|
|
107
|
+
if (enabledToolSources) body.enabledToolSources = enabledToolSources;
|
|
106
108
|
const response = await fetch(`${getBackendURL()}/${PLUGIN_ID}/chat`, {
|
|
107
109
|
method: "POST",
|
|
108
110
|
headers: {
|
|
109
111
|
"Content-Type": "application/json",
|
|
110
112
|
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
111
113
|
},
|
|
112
|
-
body: JSON.stringify(
|
|
114
|
+
body: JSON.stringify(body)
|
|
113
115
|
});
|
|
114
116
|
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
|
|
115
117
|
const reader = response.body?.getReader();
|
|
@@ -154,7 +156,7 @@ function useChat(options) {
|
|
|
154
156
|
setIsLoading(true);
|
|
155
157
|
setError(null);
|
|
156
158
|
try {
|
|
157
|
-
const reader = await fetchChatStream([...messages, userMessage]);
|
|
159
|
+
const reader = await fetchChatStream([...messages, userMessage], options?.enabledToolSources);
|
|
158
160
|
let streamStarted = false;
|
|
159
161
|
const result = await readSSEStream(reader, {
|
|
160
162
|
onTextDelta: (content) => {
|
|
@@ -386,6 +388,51 @@ function useMemories() {
|
|
|
386
388
|
}, []);
|
|
387
389
|
return { memories, loading, addMemory, editMemory, removeMemory, refresh: load };
|
|
388
390
|
}
|
|
391
|
+
const STORAGE_KEY = `${PLUGIN_ID}:enabledToolSources`;
|
|
392
|
+
function useToolSources() {
|
|
393
|
+
const [sources, setSources] = useState([]);
|
|
394
|
+
const [enabledSources, setEnabledSources] = useState(() => {
|
|
395
|
+
try {
|
|
396
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
397
|
+
if (stored) return new Set(JSON.parse(stored));
|
|
398
|
+
} catch {
|
|
399
|
+
}
|
|
400
|
+
return /* @__PURE__ */ new Set();
|
|
401
|
+
});
|
|
402
|
+
const [loaded, setLoaded] = useState(false);
|
|
403
|
+
useEffect(() => {
|
|
404
|
+
const token = getToken();
|
|
405
|
+
fetch(`${getBackendURL()}/${PLUGIN_ID}/tool-sources`, {
|
|
406
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
407
|
+
}).then((res) => res.json()).then((json) => {
|
|
408
|
+
const data = json.data ?? [];
|
|
409
|
+
setSources(data);
|
|
410
|
+
setEnabledSources((prev) => {
|
|
411
|
+
if (prev.size === 0) {
|
|
412
|
+
const all = new Set(data.filter((s) => s.id !== "built-in").map((s) => s.id));
|
|
413
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify([...all]));
|
|
414
|
+
return all;
|
|
415
|
+
}
|
|
416
|
+
return prev;
|
|
417
|
+
});
|
|
418
|
+
setLoaded(true);
|
|
419
|
+
}).catch(() => setLoaded(true));
|
|
420
|
+
}, []);
|
|
421
|
+
const toggleSource = useCallback((id) => {
|
|
422
|
+
setEnabledSources((prev) => {
|
|
423
|
+
const next = new Set(prev);
|
|
424
|
+
if (next.has(id)) next.delete(id);
|
|
425
|
+
else next.add(id);
|
|
426
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify([...next]));
|
|
427
|
+
return next;
|
|
428
|
+
});
|
|
429
|
+
}, []);
|
|
430
|
+
const enabledToolSources = useMemo(
|
|
431
|
+
() => loaded ? [...enabledSources] : void 0,
|
|
432
|
+
[enabledSources, loaded]
|
|
433
|
+
);
|
|
434
|
+
return { sources, enabledSources, enabledToolSources, toggleSource, loaded };
|
|
435
|
+
}
|
|
389
436
|
const SidebarRoot = styled.div`
|
|
390
437
|
width: ${({ $open }) => $open ? "260px" : "0px"};
|
|
391
438
|
min-width: ${({ $open }) => $open ? "260px" : "0px"};
|
|
@@ -612,6 +659,142 @@ function MemoryPanel({ memories, open, onDelete }) {
|
|
|
612
659
|
] })
|
|
613
660
|
] });
|
|
614
661
|
}
|
|
662
|
+
const Wrapper = styled.div`
|
|
663
|
+
position: relative;
|
|
664
|
+
`;
|
|
665
|
+
const IconBtn = styled.button`
|
|
666
|
+
display: flex;
|
|
667
|
+
align-items: center;
|
|
668
|
+
justify-content: center;
|
|
669
|
+
width: 32px;
|
|
670
|
+
height: 32px;
|
|
671
|
+
border: 1px solid #dcdce4;
|
|
672
|
+
border-radius: 4px;
|
|
673
|
+
background: #ffffff;
|
|
674
|
+
color: #666687;
|
|
675
|
+
cursor: pointer;
|
|
676
|
+
flex-shrink: 0;
|
|
677
|
+
|
|
678
|
+
&:hover {
|
|
679
|
+
background: #f0f0f5;
|
|
680
|
+
color: #4945ff;
|
|
681
|
+
border-color: #4945ff;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
svg {
|
|
685
|
+
width: 16px;
|
|
686
|
+
height: 16px;
|
|
687
|
+
}
|
|
688
|
+
`;
|
|
689
|
+
const Popover = styled.div`
|
|
690
|
+
position: absolute;
|
|
691
|
+
top: 40px;
|
|
692
|
+
left: 0;
|
|
693
|
+
z-index: 10;
|
|
694
|
+
width: 240px;
|
|
695
|
+
max-height: 360px;
|
|
696
|
+
overflow-y: auto;
|
|
697
|
+
background: #ffffff;
|
|
698
|
+
border: 1px solid #dcdce4;
|
|
699
|
+
border-radius: 4px;
|
|
700
|
+
box-shadow: 0 2px 12px rgba(33, 33, 52, 0.12);
|
|
701
|
+
padding: 8px 0;
|
|
702
|
+
`;
|
|
703
|
+
const SourceRow = styled.label`
|
|
704
|
+
display: flex;
|
|
705
|
+
flex-direction: column;
|
|
706
|
+
padding: 6px 12px;
|
|
707
|
+
cursor: pointer;
|
|
708
|
+
font-size: 13px;
|
|
709
|
+
color: #32324d;
|
|
710
|
+
|
|
711
|
+
&:hover {
|
|
712
|
+
background: #f6f6f9;
|
|
713
|
+
}
|
|
714
|
+
`;
|
|
715
|
+
const SourceMain = styled.div`
|
|
716
|
+
display: flex;
|
|
717
|
+
flex-direction: row;
|
|
718
|
+
align-items: center;
|
|
719
|
+
gap: 8px;
|
|
720
|
+
`;
|
|
721
|
+
const Badge = styled.div`
|
|
722
|
+
font-size: 11px;
|
|
723
|
+
color: #a5a5ba;
|
|
724
|
+
margin-left: 24px;
|
|
725
|
+
margin-top: 1px;
|
|
726
|
+
`;
|
|
727
|
+
const Toggle = styled.input`
|
|
728
|
+
accent-color: #4945ff;
|
|
729
|
+
flex-shrink: 0;
|
|
730
|
+
width: 16px;
|
|
731
|
+
height: 16px;
|
|
732
|
+
margin: 0;
|
|
733
|
+
`;
|
|
734
|
+
const Header = styled.div`
|
|
735
|
+
padding: 6px 12px 4px;
|
|
736
|
+
font-size: 11px;
|
|
737
|
+
font-weight: 600;
|
|
738
|
+
color: #a5a5ba;
|
|
739
|
+
text-transform: uppercase;
|
|
740
|
+
letter-spacing: 0.5px;
|
|
741
|
+
`;
|
|
742
|
+
function ToolSourcePicker({ sources, enabledSources, onToggle }) {
|
|
743
|
+
const [open, setOpen] = useState(false);
|
|
744
|
+
const ref = useRef(null);
|
|
745
|
+
useEffect(() => {
|
|
746
|
+
if (!open) return;
|
|
747
|
+
function handleClick(e) {
|
|
748
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
749
|
+
}
|
|
750
|
+
document.addEventListener("mousedown", handleClick);
|
|
751
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
752
|
+
}, [open]);
|
|
753
|
+
const builtIn = sources.find((s) => s.id === "built-in");
|
|
754
|
+
const plugins = sources.filter((s) => s.id !== "built-in");
|
|
755
|
+
if (sources.length === 0) return null;
|
|
756
|
+
return /* @__PURE__ */ jsxs(Wrapper, { ref, children: [
|
|
757
|
+
/* @__PURE__ */ jsx(IconBtn, { onClick: () => setOpen((p) => !p), "aria-label": "Tool sources", children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
758
|
+
/* @__PURE__ */ jsx("path", { d: "M9.5 2.5L13 6l-7 7H2.5v-3.5l7-7z" }),
|
|
759
|
+
/* @__PURE__ */ jsx("path", { d: "M8 4l4 4" })
|
|
760
|
+
] }) }),
|
|
761
|
+
open && /* @__PURE__ */ jsxs(Popover, { children: [
|
|
762
|
+
builtIn && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
763
|
+
/* @__PURE__ */ jsx(Header, { children: "Built-in" }),
|
|
764
|
+
/* @__PURE__ */ jsxs(SourceRow, { children: [
|
|
765
|
+
/* @__PURE__ */ jsxs(SourceMain, { children: [
|
|
766
|
+
/* @__PURE__ */ jsx(Toggle, { type: "checkbox", checked: true, disabled: true }),
|
|
767
|
+
builtIn.label
|
|
768
|
+
] }),
|
|
769
|
+
/* @__PURE__ */ jsxs(Badge, { children: [
|
|
770
|
+
builtIn.toolCount,
|
|
771
|
+
" tools"
|
|
772
|
+
] })
|
|
773
|
+
] })
|
|
774
|
+
] }),
|
|
775
|
+
plugins.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
776
|
+
/* @__PURE__ */ jsx(Header, { children: "Plugins" }),
|
|
777
|
+
plugins.map((s) => /* @__PURE__ */ jsxs(SourceRow, { children: [
|
|
778
|
+
/* @__PURE__ */ jsxs(SourceMain, { children: [
|
|
779
|
+
/* @__PURE__ */ jsx(
|
|
780
|
+
Toggle,
|
|
781
|
+
{
|
|
782
|
+
type: "checkbox",
|
|
783
|
+
checked: enabledSources.has(s.id),
|
|
784
|
+
onChange: () => onToggle(s.id)
|
|
785
|
+
}
|
|
786
|
+
),
|
|
787
|
+
s.label
|
|
788
|
+
] }),
|
|
789
|
+
/* @__PURE__ */ jsxs(Badge, { children: [
|
|
790
|
+
s.toolCount,
|
|
791
|
+
" tools"
|
|
792
|
+
] })
|
|
793
|
+
] }, s.id))
|
|
794
|
+
] })
|
|
795
|
+
] })
|
|
796
|
+
] });
|
|
797
|
+
}
|
|
615
798
|
const SCORE_LABELS = {
|
|
616
799
|
1: "Negligible",
|
|
617
800
|
2: "Minor",
|
|
@@ -1349,9 +1532,11 @@ function Chat() {
|
|
|
1349
1532
|
removeConversation
|
|
1350
1533
|
} = useConversations();
|
|
1351
1534
|
const { memories, removeMemory, refresh: refreshMemories } = useMemories();
|
|
1535
|
+
const { sources, enabledSources, enabledToolSources, toggleSource } = useToolSources();
|
|
1352
1536
|
const { messages, sendMessage, isLoading, error } = useChat({
|
|
1353
1537
|
initialMessages,
|
|
1354
|
-
conversationId: activeId
|
|
1538
|
+
conversationId: activeId,
|
|
1539
|
+
enabledToolSources
|
|
1355
1540
|
});
|
|
1356
1541
|
useEffect(() => {
|
|
1357
1542
|
if (prevIsLoadingRef.current && !isLoading && messages.length > 0) {
|
|
@@ -1425,6 +1610,14 @@ function Chat() {
|
|
|
1425
1610
|
] })
|
|
1426
1611
|
}
|
|
1427
1612
|
),
|
|
1613
|
+
/* @__PURE__ */ jsx(
|
|
1614
|
+
ToolSourcePicker,
|
|
1615
|
+
{
|
|
1616
|
+
sources,
|
|
1617
|
+
enabledSources,
|
|
1618
|
+
onToggle: toggleSource
|
|
1619
|
+
}
|
|
1620
|
+
),
|
|
1428
1621
|
/* @__PURE__ */ jsx("div", { style: { flex: 1 } }),
|
|
1429
1622
|
/* @__PURE__ */ jsx(
|
|
1430
1623
|
ToggleSidebarBtn,
|
|
@@ -37,7 +37,7 @@ const index = {
|
|
|
37
37
|
defaultMessage: PLUGIN_ID
|
|
38
38
|
},
|
|
39
39
|
Component: async () => {
|
|
40
|
-
const { App } = await Promise.resolve().then(() => require("./App-
|
|
40
|
+
const { App } = await Promise.resolve().then(() => require("./App-DcU3uMiY.js"));
|
|
41
41
|
return App;
|
|
42
42
|
}
|
|
43
43
|
});
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolSource } from '../hooks/useToolSources';
|
|
2
|
+
interface Props {
|
|
3
|
+
sources: ToolSource[];
|
|
4
|
+
enabledSources: Set<string>;
|
|
5
|
+
onToggle: (id: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function ToolSourcePicker({ sources, enabledSources, onToggle }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ToolSource {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
toolCount: number;
|
|
5
|
+
tools: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function useToolSources(): {
|
|
8
|
+
sources: ToolSource[];
|
|
9
|
+
enabledSources: Set<string>;
|
|
10
|
+
enabledToolSources: string[] | undefined;
|
|
11
|
+
toggleSource: (id: string) => void;
|
|
12
|
+
loaded: boolean;
|
|
13
|
+
};
|
package/dist/server/index.js
CHANGED
|
@@ -204,6 +204,29 @@ class ToolRegistry {
|
|
|
204
204
|
}
|
|
205
205
|
return result;
|
|
206
206
|
}
|
|
207
|
+
/** Returns metadata about tool sources grouped by plugin prefix */
|
|
208
|
+
getToolSources() {
|
|
209
|
+
const groups = /* @__PURE__ */ new Map();
|
|
210
|
+
for (const name of this.tools.keys()) {
|
|
211
|
+
const sepIndex = name.indexOf("__");
|
|
212
|
+
if (sepIndex === -1) {
|
|
213
|
+
const list = groups.get("built-in") ?? [];
|
|
214
|
+
list.push(name);
|
|
215
|
+
groups.set("built-in", list);
|
|
216
|
+
} else {
|
|
217
|
+
const prefix = name.substring(0, sepIndex);
|
|
218
|
+
const list = groups.get(prefix) ?? [];
|
|
219
|
+
list.push(name);
|
|
220
|
+
groups.set(prefix, list);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return Array.from(groups.entries()).map(([id, tools]) => ({
|
|
224
|
+
id,
|
|
225
|
+
label: id === "built-in" ? "Built-in Tools" : id,
|
|
226
|
+
toolCount: tools.length,
|
|
227
|
+
tools
|
|
228
|
+
}));
|
|
229
|
+
}
|
|
207
230
|
/** Only tools marked safe for unauthenticated public chat */
|
|
208
231
|
getPublicSafe() {
|
|
209
232
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -1582,7 +1605,7 @@ function validateBody(ctx) {
|
|
|
1582
1605
|
return { prompt, system };
|
|
1583
1606
|
}
|
|
1584
1607
|
function validateChatBody(ctx) {
|
|
1585
|
-
const { messages, system } = ctx.request.body;
|
|
1608
|
+
const { messages, system, enabledToolSources } = ctx.request.body;
|
|
1586
1609
|
if (!messages || !Array.isArray(messages) || messages.length === 0) {
|
|
1587
1610
|
ctx.badRequest("messages is required and must be a non-empty array");
|
|
1588
1611
|
return null;
|
|
@@ -1591,7 +1614,11 @@ function validateChatBody(ctx) {
|
|
|
1591
1614
|
ctx.badRequest("system must be a string if provided");
|
|
1592
1615
|
return null;
|
|
1593
1616
|
}
|
|
1594
|
-
|
|
1617
|
+
if (enabledToolSources !== void 0 && (!Array.isArray(enabledToolSources) || !enabledToolSources.every((s) => typeof s === "string"))) {
|
|
1618
|
+
ctx.badRequest("enabledToolSources must be an array of strings if provided");
|
|
1619
|
+
return null;
|
|
1620
|
+
}
|
|
1621
|
+
return { messages, system, enabledToolSources };
|
|
1595
1622
|
}
|
|
1596
1623
|
function createSSEStream(ctx) {
|
|
1597
1624
|
ctx.set({
|
|
@@ -1658,7 +1685,11 @@ const controller = ({ strapi }) => ({
|
|
|
1658
1685
|
const service2 = getService(strapi, ctx);
|
|
1659
1686
|
if (!service2) return;
|
|
1660
1687
|
const adminUserId = ctx.state?.user?.id;
|
|
1661
|
-
const result = await service2.chat(body.messages, {
|
|
1688
|
+
const result = await service2.chat(body.messages, {
|
|
1689
|
+
system: body.system,
|
|
1690
|
+
adminUserId,
|
|
1691
|
+
enabledToolSources: body.enabledToolSources
|
|
1692
|
+
});
|
|
1662
1693
|
const response = result.toUIMessageStreamResponse();
|
|
1663
1694
|
ctx.status = 200;
|
|
1664
1695
|
ctx.set("Content-Type", "text/event-stream; charset=utf-8");
|
|
@@ -1686,6 +1717,15 @@ const controller = ({ strapi }) => ({
|
|
|
1686
1717
|
ctx.set("x-vercel-ai-ui-message-stream", "v1");
|
|
1687
1718
|
ctx.body = node_stream.Readable.fromWeb(response.body);
|
|
1688
1719
|
},
|
|
1720
|
+
async getToolSources(ctx) {
|
|
1721
|
+
const plugin = strapi.plugin("ai-sdk");
|
|
1722
|
+
const registry = plugin.toolRegistry;
|
|
1723
|
+
if (!registry) {
|
|
1724
|
+
ctx.badRequest("Tool registry not initialized");
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
ctx.body = { data: registry.getToolSources() };
|
|
1728
|
+
},
|
|
1689
1729
|
async serveWidget(ctx) {
|
|
1690
1730
|
const pluginRoot = path__namespace.resolve(__dirname, "..", "..");
|
|
1691
1731
|
const widgetPath = path__namespace.join(pluginRoot, "dist", "widget", "widget.js");
|
|
@@ -2456,6 +2496,12 @@ const contentAPIRoutes = {
|
|
|
2456
2496
|
const adminAPIRoutes = {
|
|
2457
2497
|
type: "admin",
|
|
2458
2498
|
routes: [
|
|
2499
|
+
{
|
|
2500
|
+
method: "GET",
|
|
2501
|
+
path: "/tool-sources",
|
|
2502
|
+
handler: "controller.getToolSources",
|
|
2503
|
+
config: { policies: [] }
|
|
2504
|
+
},
|
|
2459
2505
|
{
|
|
2460
2506
|
method: "POST",
|
|
2461
2507
|
path: "/chat",
|
|
@@ -2579,8 +2625,16 @@ function createTools(strapi, context) {
|
|
|
2579
2625
|
if (!registry) {
|
|
2580
2626
|
throw new Error("Tool registry not initialized");
|
|
2581
2627
|
}
|
|
2628
|
+
const enabledSources = context?.enabledToolSources;
|
|
2582
2629
|
const tools = {};
|
|
2583
2630
|
for (const [name, def] of registry.getAll()) {
|
|
2631
|
+
if (enabledSources) {
|
|
2632
|
+
const sepIndex = name.indexOf("__");
|
|
2633
|
+
if (sepIndex !== -1) {
|
|
2634
|
+
const prefix = name.substring(0, sepIndex);
|
|
2635
|
+
if (!enabledSources.includes(prefix)) continue;
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2584
2638
|
tools[name] = ai.tool({
|
|
2585
2639
|
description: def.description,
|
|
2586
2640
|
inputSchema: ai.zodSchema(def.schema),
|
|
@@ -2704,7 +2758,7 @@ const service = ({ strapi }) => {
|
|
|
2704
2758
|
const maxSteps = config2?.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
2705
2759
|
const trimmedMessages = messages.length > maxMessages ? messages.slice(-maxMessages) : messages;
|
|
2706
2760
|
const modelMessages = await ai.convertToModelMessages(trimmedMessages);
|
|
2707
|
-
const tools = createTools(strapi, { adminUserId: options2?.adminUserId });
|
|
2761
|
+
const tools = createTools(strapi, { adminUserId: options2?.adminUserId, enabledToolSources: options2?.enabledToolSources });
|
|
2708
2762
|
const toolsDescription = describeTools(tools);
|
|
2709
2763
|
let system = composeSystemPrompt(config2, toolsDescription, options2?.system);
|
|
2710
2764
|
if (options2?.adminUserId) {
|
package/dist/server/index.mjs
CHANGED
|
@@ -184,6 +184,29 @@ class ToolRegistry {
|
|
|
184
184
|
}
|
|
185
185
|
return result;
|
|
186
186
|
}
|
|
187
|
+
/** Returns metadata about tool sources grouped by plugin prefix */
|
|
188
|
+
getToolSources() {
|
|
189
|
+
const groups = /* @__PURE__ */ new Map();
|
|
190
|
+
for (const name of this.tools.keys()) {
|
|
191
|
+
const sepIndex = name.indexOf("__");
|
|
192
|
+
if (sepIndex === -1) {
|
|
193
|
+
const list = groups.get("built-in") ?? [];
|
|
194
|
+
list.push(name);
|
|
195
|
+
groups.set("built-in", list);
|
|
196
|
+
} else {
|
|
197
|
+
const prefix = name.substring(0, sepIndex);
|
|
198
|
+
const list = groups.get(prefix) ?? [];
|
|
199
|
+
list.push(name);
|
|
200
|
+
groups.set(prefix, list);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return Array.from(groups.entries()).map(([id, tools]) => ({
|
|
204
|
+
id,
|
|
205
|
+
label: id === "built-in" ? "Built-in Tools" : id,
|
|
206
|
+
toolCount: tools.length,
|
|
207
|
+
tools
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
187
210
|
/** Only tools marked safe for unauthenticated public chat */
|
|
188
211
|
getPublicSafe() {
|
|
189
212
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -1562,7 +1585,7 @@ function validateBody(ctx) {
|
|
|
1562
1585
|
return { prompt, system };
|
|
1563
1586
|
}
|
|
1564
1587
|
function validateChatBody(ctx) {
|
|
1565
|
-
const { messages, system } = ctx.request.body;
|
|
1588
|
+
const { messages, system, enabledToolSources } = ctx.request.body;
|
|
1566
1589
|
if (!messages || !Array.isArray(messages) || messages.length === 0) {
|
|
1567
1590
|
ctx.badRequest("messages is required and must be a non-empty array");
|
|
1568
1591
|
return null;
|
|
@@ -1571,7 +1594,11 @@ function validateChatBody(ctx) {
|
|
|
1571
1594
|
ctx.badRequest("system must be a string if provided");
|
|
1572
1595
|
return null;
|
|
1573
1596
|
}
|
|
1574
|
-
|
|
1597
|
+
if (enabledToolSources !== void 0 && (!Array.isArray(enabledToolSources) || !enabledToolSources.every((s) => typeof s === "string"))) {
|
|
1598
|
+
ctx.badRequest("enabledToolSources must be an array of strings if provided");
|
|
1599
|
+
return null;
|
|
1600
|
+
}
|
|
1601
|
+
return { messages, system, enabledToolSources };
|
|
1575
1602
|
}
|
|
1576
1603
|
function createSSEStream(ctx) {
|
|
1577
1604
|
ctx.set({
|
|
@@ -1638,7 +1665,11 @@ const controller = ({ strapi }) => ({
|
|
|
1638
1665
|
const service2 = getService(strapi, ctx);
|
|
1639
1666
|
if (!service2) return;
|
|
1640
1667
|
const adminUserId = ctx.state?.user?.id;
|
|
1641
|
-
const result = await service2.chat(body.messages, {
|
|
1668
|
+
const result = await service2.chat(body.messages, {
|
|
1669
|
+
system: body.system,
|
|
1670
|
+
adminUserId,
|
|
1671
|
+
enabledToolSources: body.enabledToolSources
|
|
1672
|
+
});
|
|
1642
1673
|
const response = result.toUIMessageStreamResponse();
|
|
1643
1674
|
ctx.status = 200;
|
|
1644
1675
|
ctx.set("Content-Type", "text/event-stream; charset=utf-8");
|
|
@@ -1666,6 +1697,15 @@ const controller = ({ strapi }) => ({
|
|
|
1666
1697
|
ctx.set("x-vercel-ai-ui-message-stream", "v1");
|
|
1667
1698
|
ctx.body = Readable.fromWeb(response.body);
|
|
1668
1699
|
},
|
|
1700
|
+
async getToolSources(ctx) {
|
|
1701
|
+
const plugin = strapi.plugin("ai-sdk");
|
|
1702
|
+
const registry = plugin.toolRegistry;
|
|
1703
|
+
if (!registry) {
|
|
1704
|
+
ctx.badRequest("Tool registry not initialized");
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
ctx.body = { data: registry.getToolSources() };
|
|
1708
|
+
},
|
|
1669
1709
|
async serveWidget(ctx) {
|
|
1670
1710
|
const pluginRoot = path.resolve(__dirname, "..", "..");
|
|
1671
1711
|
const widgetPath = path.join(pluginRoot, "dist", "widget", "widget.js");
|
|
@@ -2436,6 +2476,12 @@ const contentAPIRoutes = {
|
|
|
2436
2476
|
const adminAPIRoutes = {
|
|
2437
2477
|
type: "admin",
|
|
2438
2478
|
routes: [
|
|
2479
|
+
{
|
|
2480
|
+
method: "GET",
|
|
2481
|
+
path: "/tool-sources",
|
|
2482
|
+
handler: "controller.getToolSources",
|
|
2483
|
+
config: { policies: [] }
|
|
2484
|
+
},
|
|
2439
2485
|
{
|
|
2440
2486
|
method: "POST",
|
|
2441
2487
|
path: "/chat",
|
|
@@ -2559,8 +2605,16 @@ function createTools(strapi, context) {
|
|
|
2559
2605
|
if (!registry) {
|
|
2560
2606
|
throw new Error("Tool registry not initialized");
|
|
2561
2607
|
}
|
|
2608
|
+
const enabledSources = context?.enabledToolSources;
|
|
2562
2609
|
const tools = {};
|
|
2563
2610
|
for (const [name, def] of registry.getAll()) {
|
|
2611
|
+
if (enabledSources) {
|
|
2612
|
+
const sepIndex = name.indexOf("__");
|
|
2613
|
+
if (sepIndex !== -1) {
|
|
2614
|
+
const prefix = name.substring(0, sepIndex);
|
|
2615
|
+
if (!enabledSources.includes(prefix)) continue;
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2564
2618
|
tools[name] = tool({
|
|
2565
2619
|
description: def.description,
|
|
2566
2620
|
inputSchema: zodSchema(def.schema),
|
|
@@ -2684,7 +2738,7 @@ const service = ({ strapi }) => {
|
|
|
2684
2738
|
const maxSteps = config2?.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
2685
2739
|
const trimmedMessages = messages.length > maxMessages ? messages.slice(-maxMessages) : messages;
|
|
2686
2740
|
const modelMessages = await convertToModelMessages(trimmedMessages);
|
|
2687
|
-
const tools = createTools(strapi, { adminUserId: options2?.adminUserId });
|
|
2741
|
+
const tools = createTools(strapi, { adminUserId: options2?.adminUserId, enabledToolSources: options2?.enabledToolSources });
|
|
2688
2742
|
const toolsDescription = describeTools(tools);
|
|
2689
2743
|
let system = composeSystemPrompt(config2, toolsDescription, options2?.system);
|
|
2690
2744
|
if (options2?.adminUserId) {
|
|
@@ -14,6 +14,7 @@ declare const controller: ({ strapi }: {
|
|
|
14
14
|
* Public chat endpoint - restricted tools, public memories, no admin auth
|
|
15
15
|
*/
|
|
16
16
|
publicChat(ctx: Context): Promise<void>;
|
|
17
|
+
getToolSources(ctx: Context): Promise<void>;
|
|
17
18
|
serveWidget(ctx: Context): Promise<void>;
|
|
18
19
|
};
|
|
19
20
|
export default controller;
|
|
@@ -7,6 +7,7 @@ declare const _default: {
|
|
|
7
7
|
askStream(ctx: import("koa").Context): Promise<void>;
|
|
8
8
|
chat(ctx: import("koa").Context): Promise<void>;
|
|
9
9
|
publicChat(ctx: import("koa").Context): Promise<void>;
|
|
10
|
+
getToolSources(ctx: import("koa").Context): Promise<void>;
|
|
10
11
|
serveWidget(ctx: import("koa").Context): Promise<void>;
|
|
11
12
|
};
|
|
12
13
|
mcp: ({ strapi }: {
|
|
@@ -45,6 +45,7 @@ declare const _default: {
|
|
|
45
45
|
askStream(ctx: import("koa").Context): Promise<void>;
|
|
46
46
|
chat(ctx: import("koa").Context): Promise<void>;
|
|
47
47
|
publicChat(ctx: import("koa").Context): Promise<void>;
|
|
48
|
+
getToolSources(ctx: import("koa").Context): Promise<void>;
|
|
48
49
|
serveWidget(ctx: import("koa").Context): Promise<void>;
|
|
49
50
|
};
|
|
50
51
|
mcp: ({ strapi }: {
|
|
@@ -118,7 +119,7 @@ declare const _default: {
|
|
|
118
119
|
handler: string;
|
|
119
120
|
config: {
|
|
120
121
|
policies: any[];
|
|
121
|
-
middlewares
|
|
122
|
+
middlewares?: undefined;
|
|
122
123
|
};
|
|
123
124
|
} | {
|
|
124
125
|
method: string;
|
|
@@ -126,7 +127,7 @@ declare const _default: {
|
|
|
126
127
|
handler: string;
|
|
127
128
|
config: {
|
|
128
129
|
policies: any[];
|
|
129
|
-
middlewares
|
|
130
|
+
middlewares: string[];
|
|
130
131
|
};
|
|
131
132
|
})[];
|
|
132
133
|
};
|
|
@@ -144,6 +145,7 @@ declare const _default: {
|
|
|
144
145
|
chat(messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[], options?: {
|
|
145
146
|
system?: string;
|
|
146
147
|
adminUserId?: number;
|
|
148
|
+
enabledToolSources?: string[];
|
|
147
149
|
}): Promise<import("./lib/ai-provider").StreamTextRawResult>;
|
|
148
150
|
publicChat(messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[], options?: {
|
|
149
151
|
system?: string;
|
|
@@ -2,6 +2,7 @@ import type { Core } from '@strapi/strapi';
|
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
export interface ToolContext {
|
|
4
4
|
adminUserId?: number;
|
|
5
|
+
enabledToolSources?: string[];
|
|
5
6
|
}
|
|
6
7
|
export interface ToolDefinition {
|
|
7
8
|
name: string;
|
|
@@ -25,6 +26,13 @@ export declare class ToolRegistry {
|
|
|
25
26
|
getAll(): Map<string, ToolDefinition>;
|
|
26
27
|
/** Only tools that should be exposed via MCP (non-internal) */
|
|
27
28
|
getPublic(): Map<string, ToolDefinition>;
|
|
29
|
+
/** Returns metadata about tool sources grouped by plugin prefix */
|
|
30
|
+
getToolSources(): Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
toolCount: number;
|
|
34
|
+
tools: string[];
|
|
35
|
+
}>;
|
|
28
36
|
/** Only tools marked safe for unauthenticated public chat */
|
|
29
37
|
getPublicSafe(): Map<string, ToolDefinition>;
|
|
30
38
|
}
|
|
@@ -6,7 +6,7 @@ declare const _default: {
|
|
|
6
6
|
handler: string;
|
|
7
7
|
config: {
|
|
8
8
|
policies: any[];
|
|
9
|
-
middlewares
|
|
9
|
+
middlewares?: undefined;
|
|
10
10
|
};
|
|
11
11
|
} | {
|
|
12
12
|
method: string;
|
|
@@ -14,7 +14,7 @@ declare const _default: {
|
|
|
14
14
|
handler: string;
|
|
15
15
|
config: {
|
|
16
16
|
policies: any[];
|
|
17
|
-
middlewares
|
|
17
|
+
middlewares: string[];
|
|
18
18
|
};
|
|
19
19
|
})[];
|
|
20
20
|
};
|
|
@@ -27,7 +27,7 @@ declare const routes: {
|
|
|
27
27
|
handler: string;
|
|
28
28
|
config: {
|
|
29
29
|
policies: any[];
|
|
30
|
-
middlewares
|
|
30
|
+
middlewares?: undefined;
|
|
31
31
|
};
|
|
32
32
|
} | {
|
|
33
33
|
method: string;
|
|
@@ -35,7 +35,7 @@ declare const routes: {
|
|
|
35
35
|
handler: string;
|
|
36
36
|
config: {
|
|
37
37
|
policies: any[];
|
|
38
|
-
middlewares
|
|
38
|
+
middlewares: string[];
|
|
39
39
|
};
|
|
40
40
|
})[];
|
|
41
41
|
};
|
|
@@ -11,6 +11,7 @@ declare const _default: {
|
|
|
11
11
|
chat(messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[], options?: {
|
|
12
12
|
system?: string;
|
|
13
13
|
adminUserId?: number;
|
|
14
|
+
enabledToolSources?: string[];
|
|
14
15
|
}): Promise<import("../lib/ai-provider").StreamTextRawResult>;
|
|
15
16
|
publicChat(messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[], options?: {
|
|
16
17
|
system?: string;
|
|
@@ -17,6 +17,7 @@ declare const service: ({ strapi }: {
|
|
|
17
17
|
chat(messages: UIMessage[], options?: {
|
|
18
18
|
system?: string;
|
|
19
19
|
adminUserId?: number;
|
|
20
|
+
enabledToolSources?: string[];
|
|
20
21
|
}): Promise<StreamTextRawResult>;
|
|
21
22
|
/**
|
|
22
23
|
* Public chat - restricted tools, public memories, no admin auth
|
package/package.json
CHANGED