strapi-plugin-ai-sdk 0.6.9 → 0.6.10
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-C_BH5Ir4.js → App-BGIUzHMh.js} +298 -2
- package/dist/_chunks/{App-DKyCb0BY.mjs → App-v0CobEGM.mjs} +298 -2
- package/dist/_chunks/{index-DCEjJ0as.js → index-BNk29VRc.js} +1 -1
- package/dist/_chunks/{index-BV9DET_M.mjs → index-CFO5UshL.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/TaskConfirmCard.d.ts +11 -0
- package/dist/server/index.js +478 -75
- package/dist/server/index.mjs +478 -75
- package/dist/server/src/content-types/index.d.ts +62 -0
- package/dist/server/src/content-types/task/index.d.ts +63 -0
- package/dist/server/src/controllers/index.d.ts +8 -0
- package/dist/server/src/controllers/task.d.ts +11 -0
- package/dist/server/src/index.d.ts +70 -3
- package/dist/server/src/tool-logic/index.d.ts +2 -0
- package/dist/server/src/tool-logic/manage-task.d.ts +43 -0
- package/dist/server/src/tools/definitions/manage-task.d.ts +2 -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-BNk29VRc.js");
|
|
10
10
|
const icons = require("@strapi/icons");
|
|
11
11
|
const Markdown = require("react-markdown");
|
|
12
12
|
const remarkGfm = require("remark-gfm");
|
|
@@ -618,6 +618,267 @@ function MemoryPanel({ memories, open, onDelete }) {
|
|
|
618
618
|
] })
|
|
619
619
|
] });
|
|
620
620
|
}
|
|
621
|
+
const SCORE_LABELS = {
|
|
622
|
+
1: "Negligible",
|
|
623
|
+
2: "Minor",
|
|
624
|
+
3: "Moderate",
|
|
625
|
+
4: "Significant",
|
|
626
|
+
5: "Critical"
|
|
627
|
+
};
|
|
628
|
+
const Card = styled__default.default.div`
|
|
629
|
+
margin-top: 8px;
|
|
630
|
+
border: 1px solid #dcdce4;
|
|
631
|
+
border-radius: 8px;
|
|
632
|
+
padding: 14px 16px;
|
|
633
|
+
background: #fff;
|
|
634
|
+
font-size: 13px;
|
|
635
|
+
`;
|
|
636
|
+
const Title = styled__default.default.div`
|
|
637
|
+
font-weight: 700;
|
|
638
|
+
font-size: 14px;
|
|
639
|
+
color: #32324d;
|
|
640
|
+
margin-bottom: 2px;
|
|
641
|
+
`;
|
|
642
|
+
const Description = styled__default.default.div`
|
|
643
|
+
color: #8e8ea9;
|
|
644
|
+
font-size: 12px;
|
|
645
|
+
margin-bottom: 10px;
|
|
646
|
+
`;
|
|
647
|
+
const Row = styled__default.default.div`
|
|
648
|
+
display: flex;
|
|
649
|
+
align-items: center;
|
|
650
|
+
gap: 10px;
|
|
651
|
+
margin-bottom: 8px;
|
|
652
|
+
flex-wrap: wrap;
|
|
653
|
+
`;
|
|
654
|
+
const Label = styled__default.default.label`
|
|
655
|
+
font-size: 12px;
|
|
656
|
+
font-weight: 600;
|
|
657
|
+
color: #666687;
|
|
658
|
+
min-width: 80px;
|
|
659
|
+
`;
|
|
660
|
+
const Select = styled__default.default.select`
|
|
661
|
+
padding: 4px 8px;
|
|
662
|
+
border: 1px solid #dcdce4;
|
|
663
|
+
border-radius: 4px;
|
|
664
|
+
font-size: 12px;
|
|
665
|
+
background: #fff;
|
|
666
|
+
color: #32324d;
|
|
667
|
+
`;
|
|
668
|
+
const DateInput = styled__default.default.input`
|
|
669
|
+
padding: 4px 8px;
|
|
670
|
+
border: 1px solid #dcdce4;
|
|
671
|
+
border-radius: 4px;
|
|
672
|
+
font-size: 12px;
|
|
673
|
+
color: #32324d;
|
|
674
|
+
`;
|
|
675
|
+
const AsapButton = styled__default.default.button`
|
|
676
|
+
padding: 4px 10px;
|
|
677
|
+
border: none;
|
|
678
|
+
border-radius: 4px;
|
|
679
|
+
background: #4945ff;
|
|
680
|
+
color: #fff;
|
|
681
|
+
font-size: 11px;
|
|
682
|
+
font-weight: 600;
|
|
683
|
+
cursor: pointer;
|
|
684
|
+
|
|
685
|
+
&:hover {
|
|
686
|
+
background: #3b38e0;
|
|
687
|
+
}
|
|
688
|
+
`;
|
|
689
|
+
const ScorePreview = styled__default.default.div`
|
|
690
|
+
font-size: 12px;
|
|
691
|
+
color: #666687;
|
|
692
|
+
margin-bottom: 10px;
|
|
693
|
+
font-weight: 500;
|
|
694
|
+
`;
|
|
695
|
+
const CreateButton = styled__default.default.button`
|
|
696
|
+
padding: 8px 18px;
|
|
697
|
+
border: none;
|
|
698
|
+
border-radius: 4px;
|
|
699
|
+
background: #4945ff;
|
|
700
|
+
color: #fff;
|
|
701
|
+
font-size: 13px;
|
|
702
|
+
font-weight: 600;
|
|
703
|
+
cursor: pointer;
|
|
704
|
+
|
|
705
|
+
&:disabled {
|
|
706
|
+
background: #a5a5ba;
|
|
707
|
+
cursor: not-allowed;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
&:not(:disabled):hover {
|
|
711
|
+
background: #3b38e0;
|
|
712
|
+
}
|
|
713
|
+
`;
|
|
714
|
+
const SuccessBanner = styled__default.default.div`
|
|
715
|
+
margin-top: 8px;
|
|
716
|
+
border: 1px solid #c6f0c2;
|
|
717
|
+
border-radius: 8px;
|
|
718
|
+
padding: 14px 16px;
|
|
719
|
+
background: #eafbe7;
|
|
720
|
+
font-size: 13px;
|
|
721
|
+
color: #2f6846;
|
|
722
|
+
`;
|
|
723
|
+
const SuccessTitle = styled__default.default.div`
|
|
724
|
+
font-weight: 700;
|
|
725
|
+
margin-bottom: 4px;
|
|
726
|
+
`;
|
|
727
|
+
const TaskLink = styled__default.default(reactRouterDom.Link)`
|
|
728
|
+
color: #4945ff;
|
|
729
|
+
font-weight: 600;
|
|
730
|
+
text-decoration: none;
|
|
731
|
+
font-size: 12px;
|
|
732
|
+
|
|
733
|
+
&:hover {
|
|
734
|
+
text-decoration: underline;
|
|
735
|
+
}
|
|
736
|
+
`;
|
|
737
|
+
const ErrorText = styled__default.default.div`
|
|
738
|
+
color: #d02b20;
|
|
739
|
+
font-size: 12px;
|
|
740
|
+
margin-top: 4px;
|
|
741
|
+
`;
|
|
742
|
+
function TaskConfirmCard({ proposed }) {
|
|
743
|
+
const [consequence, setConsequence] = react.useState(null);
|
|
744
|
+
const [impact, setImpact] = react.useState(null);
|
|
745
|
+
const [dueDate, setDueDate] = react.useState(proposed.dueDate ?? "");
|
|
746
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
747
|
+
const [created, setCreated] = react.useState(null);
|
|
748
|
+
const [error, setError] = react.useState(null);
|
|
749
|
+
const score = consequence != null && impact != null ? consequence * impact : null;
|
|
750
|
+
async function handleCreate() {
|
|
751
|
+
if (consequence == null || impact == null) return;
|
|
752
|
+
setSubmitting(true);
|
|
753
|
+
setError(null);
|
|
754
|
+
try {
|
|
755
|
+
const token = getToken();
|
|
756
|
+
const backend = getBackendURL();
|
|
757
|
+
const res = await fetch(`${backend}/ai-sdk/tasks`, {
|
|
758
|
+
method: "POST",
|
|
759
|
+
headers: {
|
|
760
|
+
"Content-Type": "application/json",
|
|
761
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
762
|
+
},
|
|
763
|
+
body: JSON.stringify({
|
|
764
|
+
title: proposed.title,
|
|
765
|
+
description: proposed.description,
|
|
766
|
+
content: proposed.content,
|
|
767
|
+
priority: proposed.priority,
|
|
768
|
+
consequence,
|
|
769
|
+
impact,
|
|
770
|
+
dueDate: dueDate || void 0
|
|
771
|
+
})
|
|
772
|
+
});
|
|
773
|
+
if (!res.ok) {
|
|
774
|
+
const body = await res.json().catch(() => ({}));
|
|
775
|
+
throw new Error(body.error ?? `HTTP ${res.status}`);
|
|
776
|
+
}
|
|
777
|
+
const { data } = await res.json();
|
|
778
|
+
setCreated({
|
|
779
|
+
documentId: data.documentId,
|
|
780
|
+
title: data.title,
|
|
781
|
+
consequence: data.consequence,
|
|
782
|
+
impact: data.impact,
|
|
783
|
+
priority: data.priority
|
|
784
|
+
});
|
|
785
|
+
} catch (err) {
|
|
786
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
787
|
+
} finally {
|
|
788
|
+
setSubmitting(false);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
if (created) {
|
|
792
|
+
const s = created.consequence * created.impact;
|
|
793
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(SuccessBanner, { children: [
|
|
794
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SuccessTitle, { children: [
|
|
795
|
+
"Task created: ",
|
|
796
|
+
created.title
|
|
797
|
+
] }),
|
|
798
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
799
|
+
"Score: ",
|
|
800
|
+
created.consequence,
|
|
801
|
+
" x ",
|
|
802
|
+
created.impact,
|
|
803
|
+
" = ",
|
|
804
|
+
s,
|
|
805
|
+
" · Priority: ",
|
|
806
|
+
created.priority
|
|
807
|
+
] }),
|
|
808
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ jsxRuntime.jsx(TaskLink, { to: `/content-manager/collection-types/plugin::ai-sdk.task/${created.documentId}`, children: "Open in Content Manager" }) })
|
|
809
|
+
] });
|
|
810
|
+
}
|
|
811
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
812
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Card, { children: [
|
|
813
|
+
/* @__PURE__ */ jsxRuntime.jsx(Title, { children: proposed.title }),
|
|
814
|
+
proposed.description && /* @__PURE__ */ jsxRuntime.jsx(Description, { children: proposed.description }),
|
|
815
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Row, { children: [
|
|
816
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Consequence" }),
|
|
817
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
818
|
+
Select,
|
|
819
|
+
{
|
|
820
|
+
value: consequence ?? "",
|
|
821
|
+
onChange: (e) => setConsequence(e.target.value ? Number(e.target.value) : null),
|
|
822
|
+
children: [
|
|
823
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select…" }),
|
|
824
|
+
[1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: n, children: [
|
|
825
|
+
n,
|
|
826
|
+
" — ",
|
|
827
|
+
SCORE_LABELS[n]
|
|
828
|
+
] }, n))
|
|
829
|
+
]
|
|
830
|
+
}
|
|
831
|
+
)
|
|
832
|
+
] }),
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Row, { children: [
|
|
834
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Impact" }),
|
|
835
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
836
|
+
Select,
|
|
837
|
+
{
|
|
838
|
+
value: impact ?? "",
|
|
839
|
+
onChange: (e) => setImpact(e.target.value ? Number(e.target.value) : null),
|
|
840
|
+
children: [
|
|
841
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select…" }),
|
|
842
|
+
[1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: n, children: [
|
|
843
|
+
n,
|
|
844
|
+
" — ",
|
|
845
|
+
SCORE_LABELS[n]
|
|
846
|
+
] }, n))
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
)
|
|
850
|
+
] }),
|
|
851
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Row, { children: [
|
|
852
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Due date" }),
|
|
853
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
854
|
+
DateInput,
|
|
855
|
+
{
|
|
856
|
+
type: "date",
|
|
857
|
+
value: dueDate,
|
|
858
|
+
onChange: (e) => setDueDate(e.target.value)
|
|
859
|
+
}
|
|
860
|
+
),
|
|
861
|
+
/* @__PURE__ */ jsxRuntime.jsx(AsapButton, { type: "button", onClick: () => setDueDate(today), children: "ASAP" })
|
|
862
|
+
] }),
|
|
863
|
+
score != null && /* @__PURE__ */ jsxRuntime.jsxs(ScorePreview, { children: [
|
|
864
|
+
"Score: ",
|
|
865
|
+
consequence,
|
|
866
|
+
" x ",
|
|
867
|
+
impact,
|
|
868
|
+
" = ",
|
|
869
|
+
score
|
|
870
|
+
] }),
|
|
871
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
872
|
+
CreateButton,
|
|
873
|
+
{
|
|
874
|
+
disabled: consequence == null || impact == null || submitting,
|
|
875
|
+
onClick: handleCreate,
|
|
876
|
+
children: submitting ? "Creating…" : "Create Task"
|
|
877
|
+
}
|
|
878
|
+
),
|
|
879
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(ErrorText, { children: error })
|
|
880
|
+
] });
|
|
881
|
+
}
|
|
621
882
|
function buildContentManagerUrl(contentType, documentId) {
|
|
622
883
|
const base = `/content-manager/collection-types/${contentType}`;
|
|
623
884
|
return documentId ? `${base}/${documentId}` : base;
|
|
@@ -663,6 +924,31 @@ function extractContentLinks(toolCall) {
|
|
|
663
924
|
}
|
|
664
925
|
return [];
|
|
665
926
|
}
|
|
927
|
+
const TASK_CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
928
|
+
function extractTaskLinks(toolCall) {
|
|
929
|
+
if (toolCall.toolName !== "manageTask" || toolCall.output == null) return [];
|
|
930
|
+
const output = toolCall.output;
|
|
931
|
+
if (!output.success) return [];
|
|
932
|
+
const data = output.data;
|
|
933
|
+
if (!data) return [];
|
|
934
|
+
if (!Array.isArray(data)) {
|
|
935
|
+
const docId = data.documentId;
|
|
936
|
+
const title = data.title || docId;
|
|
937
|
+
if (docId && title) {
|
|
938
|
+
return [{ label: title, to: buildContentManagerUrl(TASK_CONTENT_TYPE, docId) }];
|
|
939
|
+
}
|
|
940
|
+
return [];
|
|
941
|
+
}
|
|
942
|
+
const links = [];
|
|
943
|
+
for (const task of data.slice(0, 5)) {
|
|
944
|
+
const docId = task.documentId;
|
|
945
|
+
const title = task.title || docId;
|
|
946
|
+
if (docId && title) {
|
|
947
|
+
links.push({ label: title, to: buildContentManagerUrl(TASK_CONTENT_TYPE, docId) });
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return links;
|
|
951
|
+
}
|
|
666
952
|
const ToolCallBox = styled__default.default.div`
|
|
667
953
|
margin-top: 8px;
|
|
668
954
|
border: 1px solid #dcdce4;
|
|
@@ -747,6 +1033,13 @@ const HIDDEN_TOOLS = /* @__PURE__ */ new Set();
|
|
|
747
1033
|
function ToolCallDisplay({ toolCall }) {
|
|
748
1034
|
const [expanded, setExpanded] = react.useState(false);
|
|
749
1035
|
const contentLinks = extractContentLinks(toolCall);
|
|
1036
|
+
const taskLinks = extractTaskLinks(toolCall);
|
|
1037
|
+
if (toolCall.toolName === "manageTask" && toolCall.output != null) {
|
|
1038
|
+
const output = toolCall.output;
|
|
1039
|
+
if (output.status === "pending_confirmation" && output.proposed) {
|
|
1040
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TaskConfirmCard, { proposed: output.proposed });
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
750
1043
|
return /* @__PURE__ */ jsxRuntime.jsxs(ToolCallBox, { children: [
|
|
751
1044
|
/* @__PURE__ */ jsxRuntime.jsxs(ToolCallHeader, { onClick: () => setExpanded(!expanded), children: [
|
|
752
1045
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: expanded ? "▼" : "▶" }),
|
|
@@ -756,7 +1049,10 @@ function ToolCallDisplay({ toolCall }) {
|
|
|
756
1049
|
] }),
|
|
757
1050
|
toolCall.output === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto", fontWeight: 400, opacity: 0.6 }, children: "completed" })
|
|
758
1051
|
] }),
|
|
759
|
-
contentLinks.length > 0
|
|
1052
|
+
(contentLinks.length > 0 || taskLinks.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs(ContentLinksRow, { children: [
|
|
1053
|
+
contentLinks.map((link) => /* @__PURE__ */ jsxRuntime.jsx(ContentLinkChip, { to: link.to, children: link.label }, link.to)),
|
|
1054
|
+
taskLinks.map((link) => /* @__PURE__ */ jsxRuntime.jsx(ContentLinkChip, { to: link.to, children: link.label }, link.to))
|
|
1055
|
+
] }),
|
|
760
1056
|
expanded && /* @__PURE__ */ jsxRuntime.jsx(ToolCallContent, { children: toolCall.output === void 0 ? "Waiting for result..." : JSON.stringify(toolCall.output, null, 2) })
|
|
761
1057
|
] });
|
|
762
1058
|
}
|
|
@@ -4,7 +4,7 @@ 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
5
|
import { useState, useEffect, useCallback, forwardRef, useRef, useMemo } 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-CFO5UshL.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";
|
|
@@ -612,6 +612,267 @@ function MemoryPanel({ memories, open, onDelete }) {
|
|
|
612
612
|
] })
|
|
613
613
|
] });
|
|
614
614
|
}
|
|
615
|
+
const SCORE_LABELS = {
|
|
616
|
+
1: "Negligible",
|
|
617
|
+
2: "Minor",
|
|
618
|
+
3: "Moderate",
|
|
619
|
+
4: "Significant",
|
|
620
|
+
5: "Critical"
|
|
621
|
+
};
|
|
622
|
+
const Card = styled.div`
|
|
623
|
+
margin-top: 8px;
|
|
624
|
+
border: 1px solid #dcdce4;
|
|
625
|
+
border-radius: 8px;
|
|
626
|
+
padding: 14px 16px;
|
|
627
|
+
background: #fff;
|
|
628
|
+
font-size: 13px;
|
|
629
|
+
`;
|
|
630
|
+
const Title = styled.div`
|
|
631
|
+
font-weight: 700;
|
|
632
|
+
font-size: 14px;
|
|
633
|
+
color: #32324d;
|
|
634
|
+
margin-bottom: 2px;
|
|
635
|
+
`;
|
|
636
|
+
const Description = styled.div`
|
|
637
|
+
color: #8e8ea9;
|
|
638
|
+
font-size: 12px;
|
|
639
|
+
margin-bottom: 10px;
|
|
640
|
+
`;
|
|
641
|
+
const Row = styled.div`
|
|
642
|
+
display: flex;
|
|
643
|
+
align-items: center;
|
|
644
|
+
gap: 10px;
|
|
645
|
+
margin-bottom: 8px;
|
|
646
|
+
flex-wrap: wrap;
|
|
647
|
+
`;
|
|
648
|
+
const Label = styled.label`
|
|
649
|
+
font-size: 12px;
|
|
650
|
+
font-weight: 600;
|
|
651
|
+
color: #666687;
|
|
652
|
+
min-width: 80px;
|
|
653
|
+
`;
|
|
654
|
+
const Select = styled.select`
|
|
655
|
+
padding: 4px 8px;
|
|
656
|
+
border: 1px solid #dcdce4;
|
|
657
|
+
border-radius: 4px;
|
|
658
|
+
font-size: 12px;
|
|
659
|
+
background: #fff;
|
|
660
|
+
color: #32324d;
|
|
661
|
+
`;
|
|
662
|
+
const DateInput = styled.input`
|
|
663
|
+
padding: 4px 8px;
|
|
664
|
+
border: 1px solid #dcdce4;
|
|
665
|
+
border-radius: 4px;
|
|
666
|
+
font-size: 12px;
|
|
667
|
+
color: #32324d;
|
|
668
|
+
`;
|
|
669
|
+
const AsapButton = styled.button`
|
|
670
|
+
padding: 4px 10px;
|
|
671
|
+
border: none;
|
|
672
|
+
border-radius: 4px;
|
|
673
|
+
background: #4945ff;
|
|
674
|
+
color: #fff;
|
|
675
|
+
font-size: 11px;
|
|
676
|
+
font-weight: 600;
|
|
677
|
+
cursor: pointer;
|
|
678
|
+
|
|
679
|
+
&:hover {
|
|
680
|
+
background: #3b38e0;
|
|
681
|
+
}
|
|
682
|
+
`;
|
|
683
|
+
const ScorePreview = styled.div`
|
|
684
|
+
font-size: 12px;
|
|
685
|
+
color: #666687;
|
|
686
|
+
margin-bottom: 10px;
|
|
687
|
+
font-weight: 500;
|
|
688
|
+
`;
|
|
689
|
+
const CreateButton = styled.button`
|
|
690
|
+
padding: 8px 18px;
|
|
691
|
+
border: none;
|
|
692
|
+
border-radius: 4px;
|
|
693
|
+
background: #4945ff;
|
|
694
|
+
color: #fff;
|
|
695
|
+
font-size: 13px;
|
|
696
|
+
font-weight: 600;
|
|
697
|
+
cursor: pointer;
|
|
698
|
+
|
|
699
|
+
&:disabled {
|
|
700
|
+
background: #a5a5ba;
|
|
701
|
+
cursor: not-allowed;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
&:not(:disabled):hover {
|
|
705
|
+
background: #3b38e0;
|
|
706
|
+
}
|
|
707
|
+
`;
|
|
708
|
+
const SuccessBanner = styled.div`
|
|
709
|
+
margin-top: 8px;
|
|
710
|
+
border: 1px solid #c6f0c2;
|
|
711
|
+
border-radius: 8px;
|
|
712
|
+
padding: 14px 16px;
|
|
713
|
+
background: #eafbe7;
|
|
714
|
+
font-size: 13px;
|
|
715
|
+
color: #2f6846;
|
|
716
|
+
`;
|
|
717
|
+
const SuccessTitle = styled.div`
|
|
718
|
+
font-weight: 700;
|
|
719
|
+
margin-bottom: 4px;
|
|
720
|
+
`;
|
|
721
|
+
const TaskLink = styled(Link)`
|
|
722
|
+
color: #4945ff;
|
|
723
|
+
font-weight: 600;
|
|
724
|
+
text-decoration: none;
|
|
725
|
+
font-size: 12px;
|
|
726
|
+
|
|
727
|
+
&:hover {
|
|
728
|
+
text-decoration: underline;
|
|
729
|
+
}
|
|
730
|
+
`;
|
|
731
|
+
const ErrorText = styled.div`
|
|
732
|
+
color: #d02b20;
|
|
733
|
+
font-size: 12px;
|
|
734
|
+
margin-top: 4px;
|
|
735
|
+
`;
|
|
736
|
+
function TaskConfirmCard({ proposed }) {
|
|
737
|
+
const [consequence, setConsequence] = useState(null);
|
|
738
|
+
const [impact, setImpact] = useState(null);
|
|
739
|
+
const [dueDate, setDueDate] = useState(proposed.dueDate ?? "");
|
|
740
|
+
const [submitting, setSubmitting] = useState(false);
|
|
741
|
+
const [created, setCreated] = useState(null);
|
|
742
|
+
const [error, setError] = useState(null);
|
|
743
|
+
const score = consequence != null && impact != null ? consequence * impact : null;
|
|
744
|
+
async function handleCreate() {
|
|
745
|
+
if (consequence == null || impact == null) return;
|
|
746
|
+
setSubmitting(true);
|
|
747
|
+
setError(null);
|
|
748
|
+
try {
|
|
749
|
+
const token = getToken();
|
|
750
|
+
const backend = getBackendURL();
|
|
751
|
+
const res = await fetch(`${backend}/ai-sdk/tasks`, {
|
|
752
|
+
method: "POST",
|
|
753
|
+
headers: {
|
|
754
|
+
"Content-Type": "application/json",
|
|
755
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
756
|
+
},
|
|
757
|
+
body: JSON.stringify({
|
|
758
|
+
title: proposed.title,
|
|
759
|
+
description: proposed.description,
|
|
760
|
+
content: proposed.content,
|
|
761
|
+
priority: proposed.priority,
|
|
762
|
+
consequence,
|
|
763
|
+
impact,
|
|
764
|
+
dueDate: dueDate || void 0
|
|
765
|
+
})
|
|
766
|
+
});
|
|
767
|
+
if (!res.ok) {
|
|
768
|
+
const body = await res.json().catch(() => ({}));
|
|
769
|
+
throw new Error(body.error ?? `HTTP ${res.status}`);
|
|
770
|
+
}
|
|
771
|
+
const { data } = await res.json();
|
|
772
|
+
setCreated({
|
|
773
|
+
documentId: data.documentId,
|
|
774
|
+
title: data.title,
|
|
775
|
+
consequence: data.consequence,
|
|
776
|
+
impact: data.impact,
|
|
777
|
+
priority: data.priority
|
|
778
|
+
});
|
|
779
|
+
} catch (err) {
|
|
780
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
781
|
+
} finally {
|
|
782
|
+
setSubmitting(false);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (created) {
|
|
786
|
+
const s = created.consequence * created.impact;
|
|
787
|
+
return /* @__PURE__ */ jsxs(SuccessBanner, { children: [
|
|
788
|
+
/* @__PURE__ */ jsxs(SuccessTitle, { children: [
|
|
789
|
+
"Task created: ",
|
|
790
|
+
created.title
|
|
791
|
+
] }),
|
|
792
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
793
|
+
"Score: ",
|
|
794
|
+
created.consequence,
|
|
795
|
+
" x ",
|
|
796
|
+
created.impact,
|
|
797
|
+
" = ",
|
|
798
|
+
s,
|
|
799
|
+
" · Priority: ",
|
|
800
|
+
created.priority
|
|
801
|
+
] }),
|
|
802
|
+
/* @__PURE__ */ jsx("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ jsx(TaskLink, { to: `/content-manager/collection-types/plugin::ai-sdk.task/${created.documentId}`, children: "Open in Content Manager" }) })
|
|
803
|
+
] });
|
|
804
|
+
}
|
|
805
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
806
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
807
|
+
/* @__PURE__ */ jsx(Title, { children: proposed.title }),
|
|
808
|
+
proposed.description && /* @__PURE__ */ jsx(Description, { children: proposed.description }),
|
|
809
|
+
/* @__PURE__ */ jsxs(Row, { children: [
|
|
810
|
+
/* @__PURE__ */ jsx(Label, { children: "Consequence" }),
|
|
811
|
+
/* @__PURE__ */ jsxs(
|
|
812
|
+
Select,
|
|
813
|
+
{
|
|
814
|
+
value: consequence ?? "",
|
|
815
|
+
onChange: (e) => setConsequence(e.target.value ? Number(e.target.value) : null),
|
|
816
|
+
children: [
|
|
817
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select…" }),
|
|
818
|
+
[1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxs("option", { value: n, children: [
|
|
819
|
+
n,
|
|
820
|
+
" — ",
|
|
821
|
+
SCORE_LABELS[n]
|
|
822
|
+
] }, n))
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
)
|
|
826
|
+
] }),
|
|
827
|
+
/* @__PURE__ */ jsxs(Row, { children: [
|
|
828
|
+
/* @__PURE__ */ jsx(Label, { children: "Impact" }),
|
|
829
|
+
/* @__PURE__ */ jsxs(
|
|
830
|
+
Select,
|
|
831
|
+
{
|
|
832
|
+
value: impact ?? "",
|
|
833
|
+
onChange: (e) => setImpact(e.target.value ? Number(e.target.value) : null),
|
|
834
|
+
children: [
|
|
835
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select…" }),
|
|
836
|
+
[1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxs("option", { value: n, children: [
|
|
837
|
+
n,
|
|
838
|
+
" — ",
|
|
839
|
+
SCORE_LABELS[n]
|
|
840
|
+
] }, n))
|
|
841
|
+
]
|
|
842
|
+
}
|
|
843
|
+
)
|
|
844
|
+
] }),
|
|
845
|
+
/* @__PURE__ */ jsxs(Row, { children: [
|
|
846
|
+
/* @__PURE__ */ jsx(Label, { children: "Due date" }),
|
|
847
|
+
/* @__PURE__ */ jsx(
|
|
848
|
+
DateInput,
|
|
849
|
+
{
|
|
850
|
+
type: "date",
|
|
851
|
+
value: dueDate,
|
|
852
|
+
onChange: (e) => setDueDate(e.target.value)
|
|
853
|
+
}
|
|
854
|
+
),
|
|
855
|
+
/* @__PURE__ */ jsx(AsapButton, { type: "button", onClick: () => setDueDate(today), children: "ASAP" })
|
|
856
|
+
] }),
|
|
857
|
+
score != null && /* @__PURE__ */ jsxs(ScorePreview, { children: [
|
|
858
|
+
"Score: ",
|
|
859
|
+
consequence,
|
|
860
|
+
" x ",
|
|
861
|
+
impact,
|
|
862
|
+
" = ",
|
|
863
|
+
score
|
|
864
|
+
] }),
|
|
865
|
+
/* @__PURE__ */ jsx(
|
|
866
|
+
CreateButton,
|
|
867
|
+
{
|
|
868
|
+
disabled: consequence == null || impact == null || submitting,
|
|
869
|
+
onClick: handleCreate,
|
|
870
|
+
children: submitting ? "Creating…" : "Create Task"
|
|
871
|
+
}
|
|
872
|
+
),
|
|
873
|
+
error && /* @__PURE__ */ jsx(ErrorText, { children: error })
|
|
874
|
+
] });
|
|
875
|
+
}
|
|
615
876
|
function buildContentManagerUrl(contentType, documentId) {
|
|
616
877
|
const base = `/content-manager/collection-types/${contentType}`;
|
|
617
878
|
return documentId ? `${base}/${documentId}` : base;
|
|
@@ -657,6 +918,31 @@ function extractContentLinks(toolCall) {
|
|
|
657
918
|
}
|
|
658
919
|
return [];
|
|
659
920
|
}
|
|
921
|
+
const TASK_CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
922
|
+
function extractTaskLinks(toolCall) {
|
|
923
|
+
if (toolCall.toolName !== "manageTask" || toolCall.output == null) return [];
|
|
924
|
+
const output = toolCall.output;
|
|
925
|
+
if (!output.success) return [];
|
|
926
|
+
const data = output.data;
|
|
927
|
+
if (!data) return [];
|
|
928
|
+
if (!Array.isArray(data)) {
|
|
929
|
+
const docId = data.documentId;
|
|
930
|
+
const title = data.title || docId;
|
|
931
|
+
if (docId && title) {
|
|
932
|
+
return [{ label: title, to: buildContentManagerUrl(TASK_CONTENT_TYPE, docId) }];
|
|
933
|
+
}
|
|
934
|
+
return [];
|
|
935
|
+
}
|
|
936
|
+
const links = [];
|
|
937
|
+
for (const task of data.slice(0, 5)) {
|
|
938
|
+
const docId = task.documentId;
|
|
939
|
+
const title = task.title || docId;
|
|
940
|
+
if (docId && title) {
|
|
941
|
+
links.push({ label: title, to: buildContentManagerUrl(TASK_CONTENT_TYPE, docId) });
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return links;
|
|
945
|
+
}
|
|
660
946
|
const ToolCallBox = styled.div`
|
|
661
947
|
margin-top: 8px;
|
|
662
948
|
border: 1px solid #dcdce4;
|
|
@@ -741,6 +1027,13 @@ const HIDDEN_TOOLS = /* @__PURE__ */ new Set();
|
|
|
741
1027
|
function ToolCallDisplay({ toolCall }) {
|
|
742
1028
|
const [expanded, setExpanded] = useState(false);
|
|
743
1029
|
const contentLinks = extractContentLinks(toolCall);
|
|
1030
|
+
const taskLinks = extractTaskLinks(toolCall);
|
|
1031
|
+
if (toolCall.toolName === "manageTask" && toolCall.output != null) {
|
|
1032
|
+
const output = toolCall.output;
|
|
1033
|
+
if (output.status === "pending_confirmation" && output.proposed) {
|
|
1034
|
+
return /* @__PURE__ */ jsx(TaskConfirmCard, { proposed: output.proposed });
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
744
1037
|
return /* @__PURE__ */ jsxs(ToolCallBox, { children: [
|
|
745
1038
|
/* @__PURE__ */ jsxs(ToolCallHeader, { onClick: () => setExpanded(!expanded), children: [
|
|
746
1039
|
/* @__PURE__ */ jsx("span", { children: expanded ? "▼" : "▶" }),
|
|
@@ -750,7 +1043,10 @@ function ToolCallDisplay({ toolCall }) {
|
|
|
750
1043
|
] }),
|
|
751
1044
|
toolCall.output === void 0 ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx("span", { style: { marginLeft: "auto", fontWeight: 400, opacity: 0.6 }, children: "completed" })
|
|
752
1045
|
] }),
|
|
753
|
-
contentLinks.length > 0
|
|
1046
|
+
(contentLinks.length > 0 || taskLinks.length > 0) && /* @__PURE__ */ jsxs(ContentLinksRow, { children: [
|
|
1047
|
+
contentLinks.map((link) => /* @__PURE__ */ jsx(ContentLinkChip, { to: link.to, children: link.label }, link.to)),
|
|
1048
|
+
taskLinks.map((link) => /* @__PURE__ */ jsx(ContentLinkChip, { to: link.to, children: link.label }, link.to))
|
|
1049
|
+
] }),
|
|
754
1050
|
expanded && /* @__PURE__ */ jsx(ToolCallContent, { children: toolCall.output === void 0 ? "Waiting for result..." : JSON.stringify(toolCall.output, null, 2) })
|
|
755
1051
|
] });
|
|
756
1052
|
}
|
|
@@ -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-BGIUzHMh.js"));
|
|
41
41
|
return App;
|
|
42
42
|
}
|
|
43
43
|
});
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED