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.
- package/README.md +151 -2
- 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 +526 -76
- package/dist/server/index.mjs +526 -76
- 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/lib/tool-registry.d.ts +2 -0
- 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
package/dist/server/index.js
CHANGED
|
@@ -31,7 +31,7 @@ function _interopNamespace(e) {
|
|
|
31
31
|
const fs__namespace = /* @__PURE__ */ _interopNamespace(fs$1);
|
|
32
32
|
const path__namespace = /* @__PURE__ */ _interopNamespace(path$1);
|
|
33
33
|
function toSnakeCase(str) {
|
|
34
|
-
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
34
|
+
return str.replace(/:/g, "__").replace(/-/g, "_").replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
35
35
|
}
|
|
36
36
|
function createMcpServer(strapi) {
|
|
37
37
|
const plugin = strapi.plugin("ai-sdk");
|
|
@@ -457,7 +457,7 @@ async function sendEmail(strapi, params) {
|
|
|
457
457
|
subject: params.subject
|
|
458
458
|
};
|
|
459
459
|
}
|
|
460
|
-
const CONTENT_TYPE$
|
|
460
|
+
const CONTENT_TYPE$7 = "plugin::ai-sdk.memory";
|
|
461
461
|
const saveMemorySchema = zod.z.object({
|
|
462
462
|
content: zod.z.string().describe('A short, factual statement to remember about the user (e.g. "User prefers dark mode", "Company name is Acme Corp")'),
|
|
463
463
|
category: zod.z.string().optional().describe('Category for the memory (e.g. "preference", "project", "personal", "general"). Defaults to "general".')
|
|
@@ -468,7 +468,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
468
468
|
return { success: false, message: "Cannot save memory: user context not available." };
|
|
469
469
|
}
|
|
470
470
|
try {
|
|
471
|
-
await strapi.documents(CONTENT_TYPE$
|
|
471
|
+
await strapi.documents(CONTENT_TYPE$7).create({
|
|
472
472
|
data: {
|
|
473
473
|
content: params.content,
|
|
474
474
|
category: params.category || "general",
|
|
@@ -481,7 +481,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
481
481
|
return { success: false, message: `Failed to save memory: ${detail}` };
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
|
-
const CONTENT_TYPE$
|
|
484
|
+
const CONTENT_TYPE$6 = "plugin::ai-sdk.memory";
|
|
485
485
|
const recallMemoriesSchema = zod.z.object({
|
|
486
486
|
query: zod.z.string().optional().describe("Optional search term to filter memories by content"),
|
|
487
487
|
category: zod.z.string().optional().describe('Optional category to filter by (e.g. "preference", "project", "personal")')
|
|
@@ -499,7 +499,7 @@ async function recallMemories(strapi, params, context) {
|
|
|
499
499
|
if (params.query) {
|
|
500
500
|
filters.content = { $containsi: params.query };
|
|
501
501
|
}
|
|
502
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
502
|
+
const memories = await strapi.documents(CONTENT_TYPE$6).findMany({
|
|
503
503
|
filters,
|
|
504
504
|
fields: ["content", "category"],
|
|
505
505
|
sort: { createdAt: "desc" }
|
|
@@ -622,7 +622,7 @@ async function uploadMedia(strapi, params) {
|
|
|
622
622
|
usage: `To link this file to a content type field, use writeContent with: { "fieldName": ${uploadedFile.id} }`
|
|
623
623
|
};
|
|
624
624
|
}
|
|
625
|
-
const CONTENT_TYPE$
|
|
625
|
+
const CONTENT_TYPE$5 = "plugin::ai-sdk.public-memory";
|
|
626
626
|
const recallPublicMemoriesSchema = zod.z.object({
|
|
627
627
|
query: zod.z.string().optional().describe("Optional search term to filter public memories by content"),
|
|
628
628
|
category: zod.z.string().optional().describe('Optional category to filter by (e.g. "faq", "product", "policy")')
|
|
@@ -633,7 +633,7 @@ async function recallPublicMemories(strapi, params) {
|
|
|
633
633
|
const filters = {};
|
|
634
634
|
if (params.category) filters.category = params.category;
|
|
635
635
|
if (params.query) filters.content = { $containsi: params.query };
|
|
636
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
636
|
+
const memories = await strapi.documents(CONTENT_TYPE$5).findMany({
|
|
637
637
|
filters,
|
|
638
638
|
fields: ["content", "category"],
|
|
639
639
|
sort: { createdAt: "desc" }
|
|
@@ -867,6 +867,211 @@ async function aggregateContent(strapi, params) {
|
|
|
867
867
|
throw new Error(`Unknown operation: ${operation}`);
|
|
868
868
|
}
|
|
869
869
|
}
|
|
870
|
+
const CONTENT_TYPE$4 = "plugin::ai-sdk.task";
|
|
871
|
+
const manageTaskSchema = zod.z.object({
|
|
872
|
+
action: zod.z.enum(["create", "update", "complete", "list", "summary"]).describe(
|
|
873
|
+
"Action to perform: create a new task, update an existing task, complete (mark done), list open tasks, or get a summary."
|
|
874
|
+
),
|
|
875
|
+
documentId: zod.z.string().optional().describe("Document ID of the task to update or complete. If not known, provide title instead — the system will search for a matching task."),
|
|
876
|
+
title: zod.z.string().optional().describe("Task title — short, clear action. For update/complete: used to find the task if documentId is not provided."),
|
|
877
|
+
description: zod.z.string().optional().describe("Brief context or why this matters."),
|
|
878
|
+
content: zod.z.string().optional().describe("Detailed notes, steps, or links (markdown)."),
|
|
879
|
+
priority: zod.z.enum(["low", "medium", "high", "urgent"]).optional().describe("Priority level. Default: medium."),
|
|
880
|
+
consequence: zod.z.number().int().min(1).max(5).optional().describe("1-5: What happens if this is NOT done? Do NOT ask the user — omit this and a UI form will collect it."),
|
|
881
|
+
impact: zod.z.number().int().min(1).max(5).optional().describe("1-5: How much does completing this move the needle? Do NOT ask the user — omit this and a UI form will collect it."),
|
|
882
|
+
dueDate: zod.z.string().optional().describe("Due date in YYYY-MM-DD format."),
|
|
883
|
+
done: zod.z.boolean().optional().describe("Set done status explicitly (for update action)."),
|
|
884
|
+
filters: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Additional Strapi filters for list action.")
|
|
885
|
+
});
|
|
886
|
+
const manageTaskDescription = "Manage the user's task list. Create, update, complete, list, or summarize tasks. Tasks are scored by consequence × impact to help prioritize what matters most.";
|
|
887
|
+
async function resolveTask(strapi, adminUserId, documentId, title) {
|
|
888
|
+
if (documentId) {
|
|
889
|
+
const task2 = await strapi.documents(CONTENT_TYPE$4).findOne({ documentId });
|
|
890
|
+
if (task2 && task2.adminUserId === adminUserId) return task2;
|
|
891
|
+
}
|
|
892
|
+
if (title) {
|
|
893
|
+
const tasks = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
894
|
+
filters: {
|
|
895
|
+
adminUserId,
|
|
896
|
+
title: { $containsi: title }
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
if (tasks.length === 1) return tasks[0];
|
|
900
|
+
if (tasks.length > 1) {
|
|
901
|
+
const exact = tasks.find(
|
|
902
|
+
(t) => t.title.toLowerCase() === title.toLowerCase()
|
|
903
|
+
);
|
|
904
|
+
if (exact) return exact;
|
|
905
|
+
return tasks.sort(
|
|
906
|
+
(a, b) => b.updatedAt.localeCompare(a.updatedAt)
|
|
907
|
+
)[0];
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return null;
|
|
911
|
+
}
|
|
912
|
+
async function manageTask(strapi, params, context) {
|
|
913
|
+
if (!context?.adminUserId) {
|
|
914
|
+
return { success: false, message: "Cannot manage tasks: user context not available." };
|
|
915
|
+
}
|
|
916
|
+
const adminUserId = context.adminUserId;
|
|
917
|
+
try {
|
|
918
|
+
switch (params.action) {
|
|
919
|
+
case "create": {
|
|
920
|
+
if (!params.title) {
|
|
921
|
+
return { success: false, message: "Title is required to create a task." };
|
|
922
|
+
}
|
|
923
|
+
if (params.consequence == null || params.impact == null) {
|
|
924
|
+
return {
|
|
925
|
+
success: false,
|
|
926
|
+
status: "pending_confirmation",
|
|
927
|
+
message: "A confirmation form has been shown to the user in the chat. They will set consequence and impact scores and confirm. Do NOT re-call this tool — the task will be created when the user confirms.",
|
|
928
|
+
proposed: {
|
|
929
|
+
title: params.title,
|
|
930
|
+
description: params.description,
|
|
931
|
+
content: params.content,
|
|
932
|
+
priority: params.priority ?? "medium",
|
|
933
|
+
dueDate: params.dueDate ?? null
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
const duplicate = await resolveTask(strapi, adminUserId, void 0, params.title);
|
|
938
|
+
if (duplicate && !duplicate.done) {
|
|
939
|
+
const data = {};
|
|
940
|
+
if (params.description !== void 0) data.description = params.description;
|
|
941
|
+
if (params.content !== void 0) data.content = params.content;
|
|
942
|
+
if (params.priority !== void 0) data.priority = params.priority;
|
|
943
|
+
if (params.consequence !== void 0) data.consequence = params.consequence;
|
|
944
|
+
if (params.impact !== void 0) data.impact = params.impact;
|
|
945
|
+
if (params.dueDate !== void 0) data.dueDate = params.dueDate;
|
|
946
|
+
const updated = await strapi.documents(CONTENT_TYPE$4).update({
|
|
947
|
+
documentId: duplicate.documentId,
|
|
948
|
+
data
|
|
949
|
+
});
|
|
950
|
+
const score2 = (updated.consequence ?? 3) * (updated.impact ?? 3);
|
|
951
|
+
return {
|
|
952
|
+
success: true,
|
|
953
|
+
message: `A similar task already existed ("${duplicate.title}") — updated it instead of creating a duplicate. (priority: ${updated.priority}, score: ${score2})`,
|
|
954
|
+
data: updated
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
const task2 = await strapi.documents(CONTENT_TYPE$4).create({
|
|
958
|
+
data: {
|
|
959
|
+
title: params.title,
|
|
960
|
+
description: params.description,
|
|
961
|
+
content: params.content,
|
|
962
|
+
done: false,
|
|
963
|
+
priority: params.priority ?? "medium",
|
|
964
|
+
consequence: params.consequence ?? 3,
|
|
965
|
+
impact: params.impact ?? 3,
|
|
966
|
+
dueDate: params.dueDate,
|
|
967
|
+
adminUserId
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
const score = (task2.consequence ?? 3) * (task2.impact ?? 3);
|
|
971
|
+
return {
|
|
972
|
+
success: true,
|
|
973
|
+
message: `Task created: "${task2.title}" (priority: ${task2.priority}, score: ${score})`,
|
|
974
|
+
data: task2
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
case "update": {
|
|
978
|
+
const existing = await resolveTask(strapi, adminUserId, params.documentId, params.title);
|
|
979
|
+
if (!existing) {
|
|
980
|
+
return { success: false, message: "Task not found. Provide a documentId or a title to search by." };
|
|
981
|
+
}
|
|
982
|
+
const data = {};
|
|
983
|
+
for (const key of ["title", "description", "content", "priority", "consequence", "impact", "dueDate", "done"]) {
|
|
984
|
+
if (params[key] !== void 0) data[key] = params[key];
|
|
985
|
+
}
|
|
986
|
+
const updated = await strapi.documents(CONTENT_TYPE$4).update({
|
|
987
|
+
documentId: existing.documentId,
|
|
988
|
+
data
|
|
989
|
+
});
|
|
990
|
+
return { success: true, message: `Task updated: "${updated.title}"`, data: updated };
|
|
991
|
+
}
|
|
992
|
+
case "complete": {
|
|
993
|
+
const toComplete = await resolveTask(strapi, adminUserId, params.documentId, params.title);
|
|
994
|
+
if (!toComplete) {
|
|
995
|
+
return { success: false, message: "Task not found. Provide a documentId or a title to search by." };
|
|
996
|
+
}
|
|
997
|
+
await strapi.documents(CONTENT_TYPE$4).update({
|
|
998
|
+
documentId: toComplete.documentId,
|
|
999
|
+
data: { done: true }
|
|
1000
|
+
});
|
|
1001
|
+
return { success: true, message: `Task completed: "${toComplete.title}"` };
|
|
1002
|
+
}
|
|
1003
|
+
case "list": {
|
|
1004
|
+
const filters = {
|
|
1005
|
+
adminUserId,
|
|
1006
|
+
done: false,
|
|
1007
|
+
...params.filters
|
|
1008
|
+
};
|
|
1009
|
+
const tasks = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
1010
|
+
filters
|
|
1011
|
+
});
|
|
1012
|
+
const sorted = tasks.sort((a, b) => {
|
|
1013
|
+
const scoreA = (a.consequence ?? 3) * (a.impact ?? 3);
|
|
1014
|
+
const scoreB = (b.consequence ?? 3) * (b.impact ?? 3);
|
|
1015
|
+
if (scoreB !== scoreA) return scoreB - scoreA;
|
|
1016
|
+
if (a.dueDate && !b.dueDate) return -1;
|
|
1017
|
+
if (!a.dueDate && b.dueDate) return 1;
|
|
1018
|
+
if (a.dueDate && b.dueDate) return a.dueDate.localeCompare(b.dueDate);
|
|
1019
|
+
return 0;
|
|
1020
|
+
});
|
|
1021
|
+
return {
|
|
1022
|
+
success: true,
|
|
1023
|
+
message: `Found ${sorted.length} open task(s).`,
|
|
1024
|
+
data: sorted.map((t) => ({
|
|
1025
|
+
documentId: t.documentId,
|
|
1026
|
+
title: t.title,
|
|
1027
|
+
description: t.description,
|
|
1028
|
+
priority: t.priority,
|
|
1029
|
+
consequence: t.consequence,
|
|
1030
|
+
impact: t.impact,
|
|
1031
|
+
score: (t.consequence ?? 3) * (t.impact ?? 3),
|
|
1032
|
+
dueDate: t.dueDate,
|
|
1033
|
+
done: t.done
|
|
1034
|
+
}))
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
case "summary": {
|
|
1038
|
+
const allOpen = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
1039
|
+
filters: { adminUserId, done: false }
|
|
1040
|
+
});
|
|
1041
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1042
|
+
const overdue = allOpen.filter(
|
|
1043
|
+
(t) => t.dueDate && t.dueDate < today
|
|
1044
|
+
);
|
|
1045
|
+
const scored = allOpen.map((t) => ({
|
|
1046
|
+
documentId: t.documentId,
|
|
1047
|
+
title: t.title,
|
|
1048
|
+
priority: t.priority,
|
|
1049
|
+
consequence: t.consequence ?? 3,
|
|
1050
|
+
impact: t.impact ?? 3,
|
|
1051
|
+
score: (t.consequence ?? 3) * (t.impact ?? 3),
|
|
1052
|
+
dueDate: t.dueDate
|
|
1053
|
+
})).sort((a, b) => b.score - a.score);
|
|
1054
|
+
const urgent = scored.filter((t) => t.priority === "urgent");
|
|
1055
|
+
return {
|
|
1056
|
+
success: true,
|
|
1057
|
+
message: "Task summary generated.",
|
|
1058
|
+
data: {
|
|
1059
|
+
totalOpen: allOpen.length,
|
|
1060
|
+
overdueCount: overdue.length,
|
|
1061
|
+
overdueTasks: overdue.map((t) => ({ documentId: t.documentId, title: t.title, dueDate: t.dueDate })),
|
|
1062
|
+
urgentTasks: urgent,
|
|
1063
|
+
top3: scored.slice(0, 3)
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
default:
|
|
1068
|
+
return { success: false, message: `Unknown action: ${params.action}` };
|
|
1069
|
+
}
|
|
1070
|
+
} catch (error) {
|
|
1071
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1072
|
+
return { success: false, message: `Task operation failed: ${detail}` };
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
870
1075
|
const listContentTypesTool = {
|
|
871
1076
|
name: "listContentTypes",
|
|
872
1077
|
description: listContentTypesDescription,
|
|
@@ -979,6 +1184,13 @@ const aggregateContentTool = {
|
|
|
979
1184
|
execute: async (args, strapi) => aggregateContent(strapi, args),
|
|
980
1185
|
publicSafe: true
|
|
981
1186
|
};
|
|
1187
|
+
const manageTaskTool = {
|
|
1188
|
+
name: "manageTask",
|
|
1189
|
+
description: manageTaskDescription,
|
|
1190
|
+
schema: manageTaskSchema,
|
|
1191
|
+
execute: async (args, strapi, context) => manageTask(strapi, args, context),
|
|
1192
|
+
internal: true
|
|
1193
|
+
};
|
|
982
1194
|
const builtInTools = [
|
|
983
1195
|
listContentTypesTool,
|
|
984
1196
|
searchContentTool,
|
|
@@ -989,7 +1201,8 @@ const builtInTools = [
|
|
|
989
1201
|
saveMemoryTool,
|
|
990
1202
|
recallMemoriesTool,
|
|
991
1203
|
recallPublicMemoriesTool,
|
|
992
|
-
aggregateContentTool
|
|
1204
|
+
aggregateContentTool,
|
|
1205
|
+
manageTaskTool
|
|
993
1206
|
];
|
|
994
1207
|
const PLUGIN_ID$2 = "ai-sdk";
|
|
995
1208
|
const bootstrap = ({ strapi }) => {
|
|
@@ -1012,6 +1225,51 @@ const bootstrap = ({ strapi }) => {
|
|
|
1012
1225
|
toolRegistry.register(tool);
|
|
1013
1226
|
}
|
|
1014
1227
|
plugin.toolRegistry = toolRegistry;
|
|
1228
|
+
const pluginNames = Object.keys(strapi.plugins).filter((n) => n !== PLUGIN_ID$2);
|
|
1229
|
+
strapi.log.info(`[${PLUGIN_ID$2}] Scanning ${pluginNames.length} plugins for ai-tools: [${pluginNames.join(", ")}]`);
|
|
1230
|
+
for (const [pluginName, pluginInstance] of Object.entries(strapi.plugins)) {
|
|
1231
|
+
if (pluginName === PLUGIN_ID$2) continue;
|
|
1232
|
+
try {
|
|
1233
|
+
let aiToolsService = null;
|
|
1234
|
+
try {
|
|
1235
|
+
aiToolsService = strapi.plugin(pluginName)?.service?.("ai-tools");
|
|
1236
|
+
} catch {
|
|
1237
|
+
}
|
|
1238
|
+
if (!aiToolsService) {
|
|
1239
|
+
try {
|
|
1240
|
+
aiToolsService = pluginInstance.service?.("ai-tools");
|
|
1241
|
+
} catch {
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
if (!aiToolsService?.getTools) {
|
|
1245
|
+
strapi.log.debug(`[${PLUGIN_ID$2}] No ai-tools service on plugin: ${pluginName}`);
|
|
1246
|
+
continue;
|
|
1247
|
+
}
|
|
1248
|
+
strapi.log.info(`[${PLUGIN_ID$2}] Found ai-tools service on plugin: ${pluginName}`);
|
|
1249
|
+
const contributed = aiToolsService.getTools();
|
|
1250
|
+
if (!Array.isArray(contributed)) continue;
|
|
1251
|
+
let count = 0;
|
|
1252
|
+
for (const tool of contributed) {
|
|
1253
|
+
if (!tool.name || !tool.execute || !tool.schema) {
|
|
1254
|
+
strapi.log.warn(`[${PLUGIN_ID$2}] Invalid tool from ${pluginName}: ${tool.name || "unnamed"}`);
|
|
1255
|
+
continue;
|
|
1256
|
+
}
|
|
1257
|
+
const safeName = pluginName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1258
|
+
const namespacedName = `${safeName}__${tool.name}`;
|
|
1259
|
+
if (toolRegistry.has(namespacedName)) {
|
|
1260
|
+
strapi.log.warn(`[${PLUGIN_ID$2}] Duplicate tool: ${namespacedName}`);
|
|
1261
|
+
continue;
|
|
1262
|
+
}
|
|
1263
|
+
toolRegistry.register({ ...tool, name: namespacedName });
|
|
1264
|
+
count++;
|
|
1265
|
+
}
|
|
1266
|
+
if (count > 0) {
|
|
1267
|
+
strapi.log.info(`[${PLUGIN_ID$2}] Registered ${count} tools from plugin: ${pluginName}`);
|
|
1268
|
+
}
|
|
1269
|
+
} catch (err) {
|
|
1270
|
+
strapi.log.warn(`[${PLUGIN_ID$2}] Tool discovery failed for ${pluginName}: ${err}`);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1015
1273
|
plugin.createMcpServer = () => createMcpServer(strapi);
|
|
1016
1274
|
plugin.mcpSessions = /* @__PURE__ */ new Map();
|
|
1017
1275
|
strapi.log.info(`[${PLUGIN_ID$2}] MCP endpoint available at: /api/${PLUGIN_ID$2}/mcp`);
|
|
@@ -1098,17 +1356,17 @@ const config = {
|
|
|
1098
1356
|
}
|
|
1099
1357
|
}
|
|
1100
1358
|
};
|
|
1101
|
-
const kind$
|
|
1102
|
-
const collectionName$
|
|
1103
|
-
const info$
|
|
1359
|
+
const kind$3 = "collectionType";
|
|
1360
|
+
const collectionName$3 = "ai_sdk_conversations";
|
|
1361
|
+
const info$3 = {
|
|
1104
1362
|
singularName: "conversation",
|
|
1105
1363
|
pluralName: "conversations",
|
|
1106
1364
|
displayName: "AI Conversation"
|
|
1107
1365
|
};
|
|
1108
|
-
const options$
|
|
1366
|
+
const options$3 = {
|
|
1109
1367
|
draftAndPublish: false
|
|
1110
1368
|
};
|
|
1111
|
-
const pluginOptions$
|
|
1369
|
+
const pluginOptions$3 = {
|
|
1112
1370
|
"content-manager": {
|
|
1113
1371
|
visible: false
|
|
1114
1372
|
},
|
|
@@ -1116,7 +1374,7 @@ const pluginOptions$2 = {
|
|
|
1116
1374
|
visible: false
|
|
1117
1375
|
}
|
|
1118
1376
|
};
|
|
1119
|
-
const attributes$
|
|
1377
|
+
const attributes$3 = {
|
|
1120
1378
|
title: {
|
|
1121
1379
|
type: "string",
|
|
1122
1380
|
required: true,
|
|
@@ -1131,6 +1389,53 @@ const attributes$2 = {
|
|
|
1131
1389
|
required: true
|
|
1132
1390
|
}
|
|
1133
1391
|
};
|
|
1392
|
+
const schema$3 = {
|
|
1393
|
+
kind: kind$3,
|
|
1394
|
+
collectionName: collectionName$3,
|
|
1395
|
+
info: info$3,
|
|
1396
|
+
options: options$3,
|
|
1397
|
+
pluginOptions: pluginOptions$3,
|
|
1398
|
+
attributes: attributes$3
|
|
1399
|
+
};
|
|
1400
|
+
const conversation = { schema: schema$3 };
|
|
1401
|
+
const kind$2 = "collectionType";
|
|
1402
|
+
const collectionName$2 = "ai_sdk_memories";
|
|
1403
|
+
const info$2 = {
|
|
1404
|
+
singularName: "memory",
|
|
1405
|
+
pluralName: "memories",
|
|
1406
|
+
displayName: "AI Memory"
|
|
1407
|
+
};
|
|
1408
|
+
const options$2 = {
|
|
1409
|
+
draftAndPublish: false
|
|
1410
|
+
};
|
|
1411
|
+
const pluginOptions$2 = {
|
|
1412
|
+
"content-manager": {
|
|
1413
|
+
visible: false
|
|
1414
|
+
},
|
|
1415
|
+
"content-type-builder": {
|
|
1416
|
+
visible: false
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
const attributes$2 = {
|
|
1420
|
+
content: {
|
|
1421
|
+
type: "text",
|
|
1422
|
+
required: true
|
|
1423
|
+
},
|
|
1424
|
+
category: {
|
|
1425
|
+
type: "enumeration",
|
|
1426
|
+
"enum": [
|
|
1427
|
+
"general",
|
|
1428
|
+
"preference",
|
|
1429
|
+
"personal",
|
|
1430
|
+
"project"
|
|
1431
|
+
],
|
|
1432
|
+
"default": "general"
|
|
1433
|
+
},
|
|
1434
|
+
adminUserId: {
|
|
1435
|
+
type: "integer",
|
|
1436
|
+
required: true
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1134
1439
|
const schema$2 = {
|
|
1135
1440
|
kind: kind$2,
|
|
1136
1441
|
collectionName: collectionName$2,
|
|
@@ -1139,13 +1444,13 @@ const schema$2 = {
|
|
|
1139
1444
|
pluginOptions: pluginOptions$2,
|
|
1140
1445
|
attributes: attributes$2
|
|
1141
1446
|
};
|
|
1142
|
-
const
|
|
1447
|
+
const memory = { schema: schema$2 };
|
|
1143
1448
|
const kind$1 = "collectionType";
|
|
1144
|
-
const collectionName$1 = "
|
|
1449
|
+
const collectionName$1 = "ai_sdk_public_memories";
|
|
1145
1450
|
const info$1 = {
|
|
1146
|
-
singularName: "memory",
|
|
1147
|
-
pluralName: "memories",
|
|
1148
|
-
displayName: "AI Memory"
|
|
1451
|
+
singularName: "public-memory",
|
|
1452
|
+
pluralName: "public-memories",
|
|
1453
|
+
displayName: "AI Public Memory"
|
|
1149
1454
|
};
|
|
1150
1455
|
const options$1 = {
|
|
1151
1456
|
draftAndPublish: false
|
|
@@ -1167,15 +1472,11 @@ const attributes$1 = {
|
|
|
1167
1472
|
type: "enumeration",
|
|
1168
1473
|
"enum": [
|
|
1169
1474
|
"general",
|
|
1170
|
-
"
|
|
1171
|
-
"
|
|
1172
|
-
"
|
|
1475
|
+
"faq",
|
|
1476
|
+
"product",
|
|
1477
|
+
"policy"
|
|
1173
1478
|
],
|
|
1174
1479
|
"default": "general"
|
|
1175
|
-
},
|
|
1176
|
-
adminUserId: {
|
|
1177
|
-
type: "integer",
|
|
1178
|
-
required: true
|
|
1179
1480
|
}
|
|
1180
1481
|
};
|
|
1181
1482
|
const schema$1 = {
|
|
@@ -1186,39 +1487,68 @@ const schema$1 = {
|
|
|
1186
1487
|
pluginOptions: pluginOptions$1,
|
|
1187
1488
|
attributes: attributes$1
|
|
1188
1489
|
};
|
|
1189
|
-
const
|
|
1490
|
+
const publicMemory = { schema: schema$1 };
|
|
1190
1491
|
const kind = "collectionType";
|
|
1191
|
-
const collectionName = "
|
|
1492
|
+
const collectionName = "ai_sdk_tasks";
|
|
1192
1493
|
const info = {
|
|
1193
|
-
singularName: "
|
|
1194
|
-
pluralName: "
|
|
1195
|
-
displayName: "AI
|
|
1494
|
+
singularName: "task",
|
|
1495
|
+
pluralName: "tasks",
|
|
1496
|
+
displayName: "AI Task"
|
|
1196
1497
|
};
|
|
1197
1498
|
const options = {
|
|
1198
1499
|
draftAndPublish: false
|
|
1199
1500
|
};
|
|
1200
1501
|
const pluginOptions = {
|
|
1201
1502
|
"content-manager": {
|
|
1202
|
-
visible:
|
|
1503
|
+
visible: true
|
|
1203
1504
|
},
|
|
1204
1505
|
"content-type-builder": {
|
|
1205
1506
|
visible: false
|
|
1206
1507
|
}
|
|
1207
1508
|
};
|
|
1208
1509
|
const attributes = {
|
|
1209
|
-
|
|
1210
|
-
type: "
|
|
1510
|
+
title: {
|
|
1511
|
+
type: "string",
|
|
1211
1512
|
required: true
|
|
1212
1513
|
},
|
|
1213
|
-
|
|
1514
|
+
description: {
|
|
1515
|
+
type: "text"
|
|
1516
|
+
},
|
|
1517
|
+
content: {
|
|
1518
|
+
type: "richtext"
|
|
1519
|
+
},
|
|
1520
|
+
done: {
|
|
1521
|
+
type: "boolean",
|
|
1522
|
+
"default": false
|
|
1523
|
+
},
|
|
1524
|
+
priority: {
|
|
1214
1525
|
type: "enumeration",
|
|
1215
1526
|
"enum": [
|
|
1216
|
-
"
|
|
1217
|
-
"
|
|
1218
|
-
"
|
|
1219
|
-
"
|
|
1527
|
+
"low",
|
|
1528
|
+
"medium",
|
|
1529
|
+
"high",
|
|
1530
|
+
"urgent"
|
|
1220
1531
|
],
|
|
1221
|
-
"default": "
|
|
1532
|
+
"default": "medium"
|
|
1533
|
+
},
|
|
1534
|
+
consequence: {
|
|
1535
|
+
type: "integer",
|
|
1536
|
+
"default": 3,
|
|
1537
|
+
min: 1,
|
|
1538
|
+
max: 5
|
|
1539
|
+
},
|
|
1540
|
+
impact: {
|
|
1541
|
+
type: "integer",
|
|
1542
|
+
"default": 3,
|
|
1543
|
+
min: 1,
|
|
1544
|
+
max: 5
|
|
1545
|
+
},
|
|
1546
|
+
dueDate: {
|
|
1547
|
+
type: "date"
|
|
1548
|
+
},
|
|
1549
|
+
adminUserId: {
|
|
1550
|
+
type: "integer",
|
|
1551
|
+
required: true
|
|
1222
1552
|
}
|
|
1223
1553
|
};
|
|
1224
1554
|
const schema = {
|
|
@@ -1229,8 +1559,8 @@ const schema = {
|
|
|
1229
1559
|
pluginOptions,
|
|
1230
1560
|
attributes
|
|
1231
1561
|
};
|
|
1232
|
-
const
|
|
1233
|
-
const contentTypes = { conversation, memory, "public-memory": publicMemory };
|
|
1562
|
+
const task = { schema };
|
|
1563
|
+
const contentTypes = { conversation, memory, "public-memory": publicMemory, task };
|
|
1234
1564
|
function getService(strapi, ctx) {
|
|
1235
1565
|
const service2 = strapi.plugin("ai-sdk").service("service");
|
|
1236
1566
|
if (!service2.isInitialized()) {
|
|
@@ -1529,20 +1859,20 @@ const mcpController = ({ strapi }) => {
|
|
|
1529
1859
|
}
|
|
1530
1860
|
};
|
|
1531
1861
|
};
|
|
1532
|
-
const CONTENT_TYPE$
|
|
1533
|
-
function getAdminUserId$
|
|
1862
|
+
const CONTENT_TYPE$3 = "plugin::ai-sdk.conversation";
|
|
1863
|
+
function getAdminUserId$2(ctx) {
|
|
1534
1864
|
const id = ctx.state?.user?.id;
|
|
1535
1865
|
return typeof id === "number" ? id : null;
|
|
1536
1866
|
}
|
|
1537
1867
|
const conversationController = ({ strapi }) => ({
|
|
1538
1868
|
async find(ctx) {
|
|
1539
|
-
const adminUserId = getAdminUserId$
|
|
1869
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1540
1870
|
if (!adminUserId) {
|
|
1541
1871
|
ctx.status = 401;
|
|
1542
1872
|
ctx.body = { error: "Unauthorized" };
|
|
1543
1873
|
return;
|
|
1544
1874
|
}
|
|
1545
|
-
const conversations = await strapi.documents(CONTENT_TYPE$
|
|
1875
|
+
const conversations = await strapi.documents(CONTENT_TYPE$3).findMany({
|
|
1546
1876
|
filters: { adminUserId },
|
|
1547
1877
|
fields: ["title", "createdAt", "updatedAt"],
|
|
1548
1878
|
sort: { updatedAt: "desc" }
|
|
@@ -1550,14 +1880,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1550
1880
|
ctx.body = { data: conversations };
|
|
1551
1881
|
},
|
|
1552
1882
|
async findOne(ctx) {
|
|
1553
|
-
const adminUserId = getAdminUserId$
|
|
1883
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1554
1884
|
if (!adminUserId) {
|
|
1555
1885
|
ctx.status = 401;
|
|
1556
1886
|
ctx.body = { error: "Unauthorized" };
|
|
1557
1887
|
return;
|
|
1558
1888
|
}
|
|
1559
1889
|
const { id } = ctx.params;
|
|
1560
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
1890
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
1561
1891
|
documentId: id
|
|
1562
1892
|
});
|
|
1563
1893
|
if (!conversation2 || conversation2.adminUserId !== adminUserId) {
|
|
@@ -1568,14 +1898,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1568
1898
|
ctx.body = { data: conversation2 };
|
|
1569
1899
|
},
|
|
1570
1900
|
async create(ctx) {
|
|
1571
|
-
const adminUserId = getAdminUserId$
|
|
1901
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1572
1902
|
if (!adminUserId) {
|
|
1573
1903
|
ctx.status = 401;
|
|
1574
1904
|
ctx.body = { error: "Unauthorized" };
|
|
1575
1905
|
return;
|
|
1576
1906
|
}
|
|
1577
1907
|
const { title, messages } = ctx.request.body;
|
|
1578
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
1908
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$3).create({
|
|
1579
1909
|
data: {
|
|
1580
1910
|
title: title || "New conversation",
|
|
1581
1911
|
messages: messages || [],
|
|
@@ -1586,14 +1916,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1586
1916
|
ctx.body = { data: conversation2 };
|
|
1587
1917
|
},
|
|
1588
1918
|
async update(ctx) {
|
|
1589
|
-
const adminUserId = getAdminUserId$
|
|
1919
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1590
1920
|
if (!adminUserId) {
|
|
1591
1921
|
ctx.status = 401;
|
|
1592
1922
|
ctx.body = { error: "Unauthorized" };
|
|
1593
1923
|
return;
|
|
1594
1924
|
}
|
|
1595
1925
|
const { id } = ctx.params;
|
|
1596
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
1926
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
1597
1927
|
documentId: id
|
|
1598
1928
|
});
|
|
1599
1929
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1605,21 +1935,21 @@ const conversationController = ({ strapi }) => ({
|
|
|
1605
1935
|
const data = {};
|
|
1606
1936
|
if (title !== void 0) data.title = title;
|
|
1607
1937
|
if (messages !== void 0) data.messages = messages;
|
|
1608
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
1938
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$3).update({
|
|
1609
1939
|
documentId: id,
|
|
1610
1940
|
data
|
|
1611
1941
|
});
|
|
1612
1942
|
ctx.body = { data: conversation2 };
|
|
1613
1943
|
},
|
|
1614
1944
|
async delete(ctx) {
|
|
1615
|
-
const adminUserId = getAdminUserId$
|
|
1945
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1616
1946
|
if (!adminUserId) {
|
|
1617
1947
|
ctx.status = 401;
|
|
1618
1948
|
ctx.body = { error: "Unauthorized" };
|
|
1619
1949
|
return;
|
|
1620
1950
|
}
|
|
1621
1951
|
const { id } = ctx.params;
|
|
1622
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
1952
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
1623
1953
|
documentId: id
|
|
1624
1954
|
});
|
|
1625
1955
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1627,25 +1957,25 @@ const conversationController = ({ strapi }) => ({
|
|
|
1627
1957
|
ctx.body = { error: "Conversation not found" };
|
|
1628
1958
|
return;
|
|
1629
1959
|
}
|
|
1630
|
-
await strapi.documents(CONTENT_TYPE$
|
|
1960
|
+
await strapi.documents(CONTENT_TYPE$3).delete({ documentId: id });
|
|
1631
1961
|
ctx.status = 200;
|
|
1632
1962
|
ctx.body = { data: { documentId: id } };
|
|
1633
1963
|
}
|
|
1634
1964
|
});
|
|
1635
|
-
const CONTENT_TYPE$
|
|
1636
|
-
function getAdminUserId(ctx) {
|
|
1965
|
+
const CONTENT_TYPE$2 = "plugin::ai-sdk.memory";
|
|
1966
|
+
function getAdminUserId$1(ctx) {
|
|
1637
1967
|
const id = ctx.state?.user?.id;
|
|
1638
1968
|
return typeof id === "number" ? id : null;
|
|
1639
1969
|
}
|
|
1640
1970
|
const memoryController = ({ strapi }) => ({
|
|
1641
1971
|
async find(ctx) {
|
|
1642
|
-
const adminUserId = getAdminUserId(ctx);
|
|
1972
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
1643
1973
|
if (!adminUserId) {
|
|
1644
1974
|
ctx.status = 401;
|
|
1645
1975
|
ctx.body = { error: "Unauthorized" };
|
|
1646
1976
|
return;
|
|
1647
1977
|
}
|
|
1648
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
1978
|
+
const memories = await strapi.documents(CONTENT_TYPE$2).findMany({
|
|
1649
1979
|
filters: { adminUserId },
|
|
1650
1980
|
fields: ["content", "category", "createdAt"],
|
|
1651
1981
|
sort: { createdAt: "desc" }
|
|
@@ -1653,7 +1983,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
1653
1983
|
ctx.body = { data: memories };
|
|
1654
1984
|
},
|
|
1655
1985
|
async create(ctx) {
|
|
1656
|
-
const adminUserId = getAdminUserId(ctx);
|
|
1986
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
1657
1987
|
if (!adminUserId) {
|
|
1658
1988
|
ctx.status = 401;
|
|
1659
1989
|
ctx.body = { error: "Unauthorized" };
|
|
@@ -1665,7 +1995,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
1665
1995
|
ctx.body = { error: "content is required" };
|
|
1666
1996
|
return;
|
|
1667
1997
|
}
|
|
1668
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
1998
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).create({
|
|
1669
1999
|
data: {
|
|
1670
2000
|
content,
|
|
1671
2001
|
category: category || "general",
|
|
@@ -1676,14 +2006,14 @@ const memoryController = ({ strapi }) => ({
|
|
|
1676
2006
|
ctx.body = { data: memory2 };
|
|
1677
2007
|
},
|
|
1678
2008
|
async update(ctx) {
|
|
1679
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2009
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
1680
2010
|
if (!adminUserId) {
|
|
1681
2011
|
ctx.status = 401;
|
|
1682
2012
|
ctx.body = { error: "Unauthorized" };
|
|
1683
2013
|
return;
|
|
1684
2014
|
}
|
|
1685
2015
|
const { id } = ctx.params;
|
|
1686
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2016
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({
|
|
1687
2017
|
documentId: id
|
|
1688
2018
|
});
|
|
1689
2019
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1695,21 +2025,21 @@ const memoryController = ({ strapi }) => ({
|
|
|
1695
2025
|
const data = {};
|
|
1696
2026
|
if (content !== void 0) data.content = content;
|
|
1697
2027
|
if (category !== void 0) data.category = category;
|
|
1698
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2028
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).update({
|
|
1699
2029
|
documentId: id,
|
|
1700
2030
|
data
|
|
1701
2031
|
});
|
|
1702
2032
|
ctx.body = { data: memory2 };
|
|
1703
2033
|
},
|
|
1704
2034
|
async delete(ctx) {
|
|
1705
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2035
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
1706
2036
|
if (!adminUserId) {
|
|
1707
2037
|
ctx.status = 401;
|
|
1708
2038
|
ctx.body = { error: "Unauthorized" };
|
|
1709
2039
|
return;
|
|
1710
2040
|
}
|
|
1711
2041
|
const { id } = ctx.params;
|
|
1712
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2042
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({
|
|
1713
2043
|
documentId: id
|
|
1714
2044
|
});
|
|
1715
2045
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1717,15 +2047,15 @@ const memoryController = ({ strapi }) => ({
|
|
|
1717
2047
|
ctx.body = { error: "Memory not found" };
|
|
1718
2048
|
return;
|
|
1719
2049
|
}
|
|
1720
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2050
|
+
await strapi.documents(CONTENT_TYPE$2).delete({ documentId: id });
|
|
1721
2051
|
ctx.status = 200;
|
|
1722
2052
|
ctx.body = { data: { documentId: id } };
|
|
1723
2053
|
}
|
|
1724
2054
|
});
|
|
1725
|
-
const CONTENT_TYPE = "plugin::ai-sdk.public-memory";
|
|
2055
|
+
const CONTENT_TYPE$1 = "plugin::ai-sdk.public-memory";
|
|
1726
2056
|
const publicMemoryController = ({ strapi }) => ({
|
|
1727
2057
|
async find(ctx) {
|
|
1728
|
-
const memories = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2058
|
+
const memories = await strapi.documents(CONTENT_TYPE$1).findMany({
|
|
1729
2059
|
fields: ["content", "category", "createdAt"],
|
|
1730
2060
|
sort: { createdAt: "desc" }
|
|
1731
2061
|
});
|
|
@@ -1738,7 +2068,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
1738
2068
|
ctx.body = { error: "content is required" };
|
|
1739
2069
|
return;
|
|
1740
2070
|
}
|
|
1741
|
-
const memory2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2071
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$1).create({
|
|
1742
2072
|
data: { content, category: category || "general" }
|
|
1743
2073
|
});
|
|
1744
2074
|
ctx.status = 201;
|
|
@@ -1746,7 +2076,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
1746
2076
|
},
|
|
1747
2077
|
async update(ctx) {
|
|
1748
2078
|
const { id } = ctx.params;
|
|
1749
|
-
const existing = await strapi.documents(CONTENT_TYPE).findOne({ documentId: id });
|
|
2079
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({ documentId: id });
|
|
1750
2080
|
if (!existing) {
|
|
1751
2081
|
ctx.status = 404;
|
|
1752
2082
|
ctx.body = { error: "Public memory not found" };
|
|
@@ -1756,7 +2086,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
1756
2086
|
const data = {};
|
|
1757
2087
|
if (content !== void 0) data.content = content;
|
|
1758
2088
|
if (category !== void 0) data.category = category;
|
|
1759
|
-
const memory2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2089
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$1).update({
|
|
1760
2090
|
documentId: id,
|
|
1761
2091
|
data
|
|
1762
2092
|
});
|
|
@@ -1764,12 +2094,103 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
1764
2094
|
},
|
|
1765
2095
|
async delete(ctx) {
|
|
1766
2096
|
const { id } = ctx.params;
|
|
1767
|
-
const existing = await strapi.documents(CONTENT_TYPE).findOne({ documentId: id });
|
|
2097
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({ documentId: id });
|
|
1768
2098
|
if (!existing) {
|
|
1769
2099
|
ctx.status = 404;
|
|
1770
2100
|
ctx.body = { error: "Public memory not found" };
|
|
1771
2101
|
return;
|
|
1772
2102
|
}
|
|
2103
|
+
await strapi.documents(CONTENT_TYPE$1).delete({ documentId: id });
|
|
2104
|
+
ctx.status = 200;
|
|
2105
|
+
ctx.body = { data: { documentId: id } };
|
|
2106
|
+
}
|
|
2107
|
+
});
|
|
2108
|
+
const CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
2109
|
+
function getAdminUserId(ctx) {
|
|
2110
|
+
const id = ctx.state?.user?.id;
|
|
2111
|
+
return typeof id === "number" ? id : null;
|
|
2112
|
+
}
|
|
2113
|
+
const taskController = ({ strapi }) => ({
|
|
2114
|
+
async find(ctx) {
|
|
2115
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2116
|
+
if (!adminUserId) {
|
|
2117
|
+
ctx.status = 401;
|
|
2118
|
+
ctx.body = { error: "Unauthorized" };
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
const tasks = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2122
|
+
filters: { adminUserId },
|
|
2123
|
+
sort: { createdAt: "desc" }
|
|
2124
|
+
});
|
|
2125
|
+
ctx.body = { data: tasks };
|
|
2126
|
+
},
|
|
2127
|
+
async create(ctx) {
|
|
2128
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2129
|
+
if (!adminUserId) {
|
|
2130
|
+
ctx.status = 401;
|
|
2131
|
+
ctx.body = { error: "Unauthorized" };
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
const body = ctx.request.body;
|
|
2135
|
+
const task2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2136
|
+
data: {
|
|
2137
|
+
title: body.title,
|
|
2138
|
+
description: body.description,
|
|
2139
|
+
content: body.content,
|
|
2140
|
+
done: body.done ?? false,
|
|
2141
|
+
priority: body.priority ?? "medium",
|
|
2142
|
+
consequence: body.consequence ?? 3,
|
|
2143
|
+
impact: body.impact ?? 3,
|
|
2144
|
+
dueDate: body.dueDate,
|
|
2145
|
+
adminUserId
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
ctx.status = 201;
|
|
2149
|
+
ctx.body = { data: task2 };
|
|
2150
|
+
},
|
|
2151
|
+
async update(ctx) {
|
|
2152
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2153
|
+
if (!adminUserId) {
|
|
2154
|
+
ctx.status = 401;
|
|
2155
|
+
ctx.body = { error: "Unauthorized" };
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
const { id } = ctx.params;
|
|
2159
|
+
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2160
|
+
documentId: id
|
|
2161
|
+
});
|
|
2162
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2163
|
+
ctx.status = 404;
|
|
2164
|
+
ctx.body = { error: "Task not found" };
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
const body = ctx.request.body;
|
|
2168
|
+
const data = {};
|
|
2169
|
+
for (const key of ["title", "description", "content", "done", "priority", "consequence", "impact", "dueDate"]) {
|
|
2170
|
+
if (body[key] !== void 0) data[key] = body[key];
|
|
2171
|
+
}
|
|
2172
|
+
const task2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2173
|
+
documentId: id,
|
|
2174
|
+
data
|
|
2175
|
+
});
|
|
2176
|
+
ctx.body = { data: task2 };
|
|
2177
|
+
},
|
|
2178
|
+
async delete(ctx) {
|
|
2179
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2180
|
+
if (!adminUserId) {
|
|
2181
|
+
ctx.status = 401;
|
|
2182
|
+
ctx.body = { error: "Unauthorized" };
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
const { id } = ctx.params;
|
|
2186
|
+
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2187
|
+
documentId: id
|
|
2188
|
+
});
|
|
2189
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2190
|
+
ctx.status = 404;
|
|
2191
|
+
ctx.body = { error: "Task not found" };
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
1773
2194
|
await strapi.documents(CONTENT_TYPE).delete({ documentId: id });
|
|
1774
2195
|
ctx.status = 200;
|
|
1775
2196
|
ctx.body = { data: { documentId: id } };
|
|
@@ -1780,7 +2201,8 @@ const controllers = {
|
|
|
1780
2201
|
mcp: mcpController,
|
|
1781
2202
|
conversation: conversationController,
|
|
1782
2203
|
memory: memoryController,
|
|
1783
|
-
"public-memory": publicMemoryController
|
|
2204
|
+
"public-memory": publicMemoryController,
|
|
2205
|
+
task: taskController
|
|
1784
2206
|
};
|
|
1785
2207
|
const promptInjection = [
|
|
1786
2208
|
"ignore (all |any )?(previous|prior|above) (instructions|prompts|rules)",
|
|
@@ -2120,6 +2542,30 @@ const adminAPIRoutes = {
|
|
|
2120
2542
|
path: "/public-memories/:id",
|
|
2121
2543
|
handler: "public-memory.delete",
|
|
2122
2544
|
config: { policies: [] }
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
method: "GET",
|
|
2548
|
+
path: "/tasks",
|
|
2549
|
+
handler: "task.find",
|
|
2550
|
+
config: { policies: [] }
|
|
2551
|
+
},
|
|
2552
|
+
{
|
|
2553
|
+
method: "POST",
|
|
2554
|
+
path: "/tasks",
|
|
2555
|
+
handler: "task.create",
|
|
2556
|
+
config: { policies: [] }
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
method: "PUT",
|
|
2560
|
+
path: "/tasks/:id",
|
|
2561
|
+
handler: "task.update",
|
|
2562
|
+
config: { policies: [] }
|
|
2563
|
+
},
|
|
2564
|
+
{
|
|
2565
|
+
method: "DELETE",
|
|
2566
|
+
path: "/tasks/:id",
|
|
2567
|
+
handler: "task.delete",
|
|
2568
|
+
config: { policies: [] }
|
|
2123
2569
|
}
|
|
2124
2570
|
]
|
|
2125
2571
|
};
|
|
@@ -2197,12 +2643,16 @@ const DEFAULT_PREAMBLE = `You are a Strapi CMS assistant. Use your tools to fulf
|
|
|
2197
2643
|
|
|
2198
2644
|
For analytics and counting questions (e.g. "how many", "count", "distribution", "trends", "breakdown"), use the aggregateContent tool instead of searchContent — it is faster and purpose-built for these queries. Present analytics results as markdown tables. After showing analytics results, suggest 2-3 follow-up questions the user might find useful under a "**You might also want to know:**" heading.
|
|
2199
2645
|
|
|
2646
|
+
Plugin tools: When specialized tools from plugins are available (listed below), ALWAYS prefer them over the generic searchContent tool. For example, use searchMentions for social mentions (it has BM25 relevance scoring), semanticSearch for vector similarity search across embeddings, and ragQuery for question-answering grounded in embedded content. Only fall back to searchContent when no specialized tool covers the query.
|
|
2647
|
+
|
|
2200
2648
|
Strapi filter syntax for searchContent and aggregateContent:
|
|
2201
2649
|
- Scalar fields: { title: { $containsi: "hello" } }
|
|
2202
2650
|
- Relation (manyToOne): { author: { name: { $eq: "John" } } }
|
|
2203
2651
|
- Relation (manyToMany): { contentTags: { title: { $eq: "tutorial" } } }
|
|
2204
2652
|
- Always nest relation filters as: { relationField: { fieldOnRelatedType: { $operator: value } } }
|
|
2205
|
-
- Never use flat dot-path syntax like "contentTags.title" in filters — always use nested objects
|
|
2653
|
+
- Never use flat dot-path syntax like "contentTags.title" in filters — always use nested objects.
|
|
2654
|
+
|
|
2655
|
+
Task management: You have a manageTask tool for tracking the user's tasks. At the START of every conversation, proactively use manageTask with action "summary" to check for open tasks, then greet the user with a brief status and suggest what to tackle next based on consequence × impact score. When the user mentions action items, commitments, or things they need to do during conversation, proactively create tasks by calling manageTask with action "create" — do NOT include consequence or impact scores, just omit them. A UI form will appear in the chat for the user to set scores and confirm. Never ask for scores in text. When presenting task lists, use markdown tables.`;
|
|
2206
2656
|
const DEFAULT_PUBLIC_PREAMBLE = `You are a helpful public assistant for this website. Use your tools to answer questions about the site content. You cannot modify any content or perform administrative actions.
|
|
2207
2657
|
|
|
2208
2658
|
For analytics and counting questions (e.g. "how many", "count", "distribution", "trends", "breakdown"), use the aggregateContent tool instead of searchContent — it is faster and purpose-built for these queries. Present analytics results as markdown tables. After showing analytics results, suggest 2-3 follow-up questions the user might find useful under a "**You might also want to know:**" heading.
|