strapi-plugin-ai-sdk 0.6.9 → 0.7.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.
@@ -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-BV9DET_M.mjs";
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 && /* @__PURE__ */ jsx(ContentLinksRow, { children: contentLinks.map((link) => /* @__PURE__ */ jsx(ContentLinkChip, { to: link.to, children: link.label }, link.to)) }),
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-C_BH5Ir4.js"));
40
+ const { App } = await Promise.resolve().then(() => require("./App-BGIUzHMh.js"));
41
41
  return App;
42
42
  }
43
43
  });
@@ -36,7 +36,7 @@ const index = {
36
36
  defaultMessage: PLUGIN_ID
37
37
  },
38
38
  Component: async () => {
39
- const { App } = await import("./App-DKyCb0BY.mjs");
39
+ const { App } = await import("./App-v0CobEGM.mjs");
40
40
  return App;
41
41
  }
42
42
  });
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-DCEjJ0as.js");
2
+ const index = require("../_chunks/index-BNk29VRc.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-BV9DET_M.mjs";
1
+ import { i } from "../_chunks/index-CFO5UshL.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -0,0 +1,11 @@
1
+ interface Proposed {
2
+ title: string;
3
+ description?: string;
4
+ content?: string;
5
+ priority: string;
6
+ dueDate: string | null;
7
+ }
8
+ export declare function TaskConfirmCard({ proposed }: Readonly<{
9
+ proposed: Proposed;
10
+ }>): import("react/jsx-runtime").JSX.Element;
11
+ export {};