strapi-plugin-ai-sdk 0.7.7 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{App-joEmdpxi.js → App-DTbAnq7K.js} +710 -51
- package/dist/_chunks/{App-DMdQymB3.mjs → App-DZVBmpvs.mjs} +712 -53
- package/dist/_chunks/{index-B7qLITWV.js → index-C3xn2IND.js} +1 -1
- package/dist/_chunks/{index-DrLcqX__.mjs → index-Ca2F2wBp.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/NotePanel.d.ts +15 -0
- package/dist/admin/src/hooks/useNotes.d.ts +22 -0
- package/dist/admin/src/pages/NoteStorePage.d.ts +2 -0
- package/dist/admin/src/utils/notes-api.d.ts +28 -0
- package/dist/server/index.js +536 -121
- package/dist/server/index.mjs +536 -121
- package/dist/server/src/content-types/index.d.ts +46 -0
- package/dist/server/src/content-types/note/index.d.ts +47 -0
- package/dist/server/src/controllers/index.d.ts +9 -0
- package/dist/server/src/controllers/note.d.ts +12 -0
- package/dist/server/src/index.d.ts +55 -0
- package/dist/server/src/lib/trim-messages.d.ts +11 -0
- package/dist/server/src/mcp/resources/tool-guide.d.ts +5 -0
- package/dist/server/src/tool-logic/aggregate-content.d.ts +1 -1
- package/dist/server/src/tool-logic/create-content.d.ts +1 -1
- package/dist/server/src/tool-logic/find-one-content.d.ts +1 -1
- package/dist/server/src/tool-logic/index.d.ts +4 -0
- package/dist/server/src/tool-logic/list-content-types.d.ts +1 -1
- package/dist/server/src/tool-logic/manage-task.d.ts +1 -1
- package/dist/server/src/tool-logic/recall-notes.d.ts +22 -0
- package/dist/server/src/tool-logic/save-note.d.ts +17 -0
- package/dist/server/src/tool-logic/update-content.d.ts +1 -1
- package/dist/server/src/tool-logic/upload-media.d.ts +1 -1
- package/dist/server/src/tools/definitions/recall-notes.d.ts +2 -0
- package/dist/server/src/tools/definitions/save-note.d.ts +2 -0
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -30,6 +30,90 @@ function _interopNamespace(e) {
|
|
|
30
30
|
}
|
|
31
31
|
const fs__namespace = /* @__PURE__ */ _interopNamespace(fs$1);
|
|
32
32
|
const path__namespace = /* @__PURE__ */ _interopNamespace(path$1);
|
|
33
|
+
function toSnakeCase$1(str) {
|
|
34
|
+
return str.replace(/:/g, "__").replace(/-/g, "_").replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
35
|
+
}
|
|
36
|
+
function extractType(field) {
|
|
37
|
+
const def = field?._zod?.def;
|
|
38
|
+
if (!def) return "unknown";
|
|
39
|
+
switch (def.type) {
|
|
40
|
+
case "string":
|
|
41
|
+
return "string";
|
|
42
|
+
case "number":
|
|
43
|
+
return "number";
|
|
44
|
+
case "boolean":
|
|
45
|
+
return "boolean";
|
|
46
|
+
case "enum":
|
|
47
|
+
return Object.keys(def.entries).join(" | ");
|
|
48
|
+
case "optional":
|
|
49
|
+
return extractType({ _zod: { def: def.innerType } });
|
|
50
|
+
case "default":
|
|
51
|
+
return extractType({ _zod: { def: def.innerType } });
|
|
52
|
+
case "record":
|
|
53
|
+
return "object";
|
|
54
|
+
case "array":
|
|
55
|
+
return "array";
|
|
56
|
+
case "union":
|
|
57
|
+
return "string | array | object";
|
|
58
|
+
default:
|
|
59
|
+
return def.type || "unknown";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function formatParams(schema2) {
|
|
63
|
+
const shape = schema2.shape;
|
|
64
|
+
if (!shape || Object.keys(shape).length === 0) {
|
|
65
|
+
return "_No parameters._\n";
|
|
66
|
+
}
|
|
67
|
+
const rows = [];
|
|
68
|
+
rows.push("| Parameter | Type | Required | Description |");
|
|
69
|
+
rows.push("|-----------|------|----------|-------------|");
|
|
70
|
+
for (const [name, field] of Object.entries(shape)) {
|
|
71
|
+
const required = !field.isOptional?.();
|
|
72
|
+
const type = extractType(field);
|
|
73
|
+
const desc = (field.description || "").replace(/\|/g, "\\|");
|
|
74
|
+
rows.push(`| ${name} | ${type} | ${required ? "Yes" : "No"} | ${desc} |`);
|
|
75
|
+
}
|
|
76
|
+
return rows.join("\n") + "\n";
|
|
77
|
+
}
|
|
78
|
+
function generateToolGuide(registry) {
|
|
79
|
+
const tools = registry.getPublic();
|
|
80
|
+
const sources = registry.getToolSources();
|
|
81
|
+
const sections = [];
|
|
82
|
+
sections.push("# Strapi AI Tools Guide\n");
|
|
83
|
+
sections.push("## Getting Started\n");
|
|
84
|
+
sections.push(
|
|
85
|
+
"Start with `list_content_types` to discover your content types and their fields, then use `search_content` to query them.\n"
|
|
86
|
+
);
|
|
87
|
+
for (const source of sources) {
|
|
88
|
+
const heading = source.id === "built-in" ? "Built-in Tools" : source.label;
|
|
89
|
+
sections.push(`## ${heading}
|
|
90
|
+
`);
|
|
91
|
+
for (const toolName of source.tools) {
|
|
92
|
+
const def = tools.get(toolName);
|
|
93
|
+
if (!def) continue;
|
|
94
|
+
const mcpName = toSnakeCase$1(toolName);
|
|
95
|
+
sections.push(`### ${mcpName}
|
|
96
|
+
`);
|
|
97
|
+
sections.push(`${def.description}
|
|
98
|
+
`);
|
|
99
|
+
sections.push(formatParams(def.schema));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
sections.push("## Common Workflows\n");
|
|
103
|
+
sections.push("### Create a blog post\n");
|
|
104
|
+
sections.push(
|
|
105
|
+
"1. Call `list_content_types` to discover the article/blog content type and its fields\n2. (Optional) Call `upload_media` with a URL to upload a cover image\n3. Call `create_content` with the content type UID and field data\n"
|
|
106
|
+
);
|
|
107
|
+
sections.push("### Find and update content\n");
|
|
108
|
+
sections.push(
|
|
109
|
+
"1. Call `search_content` with filters or a query to find the document\n2. Note the `documentId` from the results\n3. Call `update_content` with the content type, documentId, and fields to change\n"
|
|
110
|
+
);
|
|
111
|
+
sections.push("### Content analytics\n");
|
|
112
|
+
sections.push(
|
|
113
|
+
"1. Call `aggregate_content` with operation `count` for totals\n2. Use `countByField` with `groupByField` to see distribution (e.g. articles per category)\n3. Use `countByDateRange` with `granularity` to see trends over time\n"
|
|
114
|
+
);
|
|
115
|
+
return sections.join("\n");
|
|
116
|
+
}
|
|
33
117
|
function toSnakeCase(str) {
|
|
34
118
|
return str.replace(/:/g, "__").replace(/-/g, "_").replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
35
119
|
}
|
|
@@ -46,7 +130,8 @@ function createMcpServer(strapi) {
|
|
|
46
130
|
},
|
|
47
131
|
{
|
|
48
132
|
capabilities: {
|
|
49
|
-
tools: {}
|
|
133
|
+
tools: {},
|
|
134
|
+
resources: {}
|
|
50
135
|
}
|
|
51
136
|
}
|
|
52
137
|
);
|
|
@@ -74,6 +159,24 @@ function createMcpServer(strapi) {
|
|
|
74
159
|
}
|
|
75
160
|
);
|
|
76
161
|
}
|
|
162
|
+
const guideMarkdown = generateToolGuide(registry);
|
|
163
|
+
server.registerResource(
|
|
164
|
+
"Tool Guide",
|
|
165
|
+
"strapi://tools/guide",
|
|
166
|
+
{
|
|
167
|
+
description: "Complete guide to all available Strapi AI tools with parameters and usage examples",
|
|
168
|
+
mimeType: "text/markdown"
|
|
169
|
+
},
|
|
170
|
+
async () => ({
|
|
171
|
+
contents: [
|
|
172
|
+
{
|
|
173
|
+
uri: "strapi://tools/guide",
|
|
174
|
+
mimeType: "text/markdown",
|
|
175
|
+
text: guideMarkdown
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
})
|
|
179
|
+
);
|
|
77
180
|
strapi.log.info("[ai-sdk:mcp] MCP server created with tools:", { tools: toolNames });
|
|
78
181
|
return server;
|
|
79
182
|
}
|
|
@@ -239,7 +342,7 @@ class ToolRegistry {
|
|
|
239
342
|
}
|
|
240
343
|
}
|
|
241
344
|
const listContentTypesSchema = zod.z.object({});
|
|
242
|
-
const listContentTypesDescription =
|
|
345
|
+
const listContentTypesDescription = 'List all Strapi content types and components with their fields, relations, and structure. This is the starting point for any content operation — call it first to discover content type UIDs (e.g. "api::article.article"), field names, relation targets, and components. No parameters required. Results are cached.';
|
|
243
346
|
const INTERNAL_FIELDS = /* @__PURE__ */ new Set([
|
|
244
347
|
"createdAt",
|
|
245
348
|
"updatedAt",
|
|
@@ -393,7 +496,7 @@ const createContentSchema = zod.z.object({
|
|
|
393
496
|
status: zod.z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
394
497
|
locale: zod.z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
395
498
|
});
|
|
396
|
-
const createContentDescription = "Create a new document in any Strapi content type (
|
|
499
|
+
const createContentDescription = "Create a new document in any Strapi content type. Requires contentType (UID) and data (field values). Call listContentTypes first to discover UIDs and required fields. To attach media, upload it first with uploadMedia, then pass the file ID in data. Returns the created document with all fields populated.";
|
|
397
500
|
async function createContent(strapi, params) {
|
|
398
501
|
const { contentType, data, status, locale } = params;
|
|
399
502
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -415,7 +518,7 @@ const updateContentSchema = zod.z.object({
|
|
|
415
518
|
status: zod.z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
416
519
|
locale: zod.z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
417
520
|
});
|
|
418
|
-
const updateContentDescription = "Update an existing document in any Strapi content type.
|
|
521
|
+
const updateContentDescription = "Update an existing document in any Strapi content type. Requires contentType, documentId, and data (fields to change — only include fields you want to modify). Typical workflow: searchContent to find the documentId, then updateContent to modify it. Returns the updated document.";
|
|
419
522
|
async function updateContent(strapi, params) {
|
|
420
523
|
const { contentType, documentId, data, status, locale } = params;
|
|
421
524
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -488,7 +591,7 @@ async function sendEmail(strapi, params) {
|
|
|
488
591
|
subject: params.subject
|
|
489
592
|
};
|
|
490
593
|
}
|
|
491
|
-
const CONTENT_TYPE$
|
|
594
|
+
const CONTENT_TYPE$a = "plugin::ai-sdk.memory";
|
|
492
595
|
const saveMemorySchema = zod.z.object({
|
|
493
596
|
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")'),
|
|
494
597
|
category: zod.z.string().optional().describe('Category for the memory (e.g. "preference", "project", "personal", "general"). Defaults to "general".')
|
|
@@ -499,7 +602,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
499
602
|
return { success: false, message: "Cannot save memory: user context not available." };
|
|
500
603
|
}
|
|
501
604
|
try {
|
|
502
|
-
await strapi.documents(CONTENT_TYPE$
|
|
605
|
+
await strapi.documents(CONTENT_TYPE$a).create({
|
|
503
606
|
data: {
|
|
504
607
|
content: params.content,
|
|
505
608
|
category: params.category || "general",
|
|
@@ -512,7 +615,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
512
615
|
return { success: false, message: `Failed to save memory: ${detail}` };
|
|
513
616
|
}
|
|
514
617
|
}
|
|
515
|
-
const CONTENT_TYPE$
|
|
618
|
+
const CONTENT_TYPE$9 = "plugin::ai-sdk.memory";
|
|
516
619
|
const recallMemoriesSchema = zod.z.object({
|
|
517
620
|
query: zod.z.string().optional().describe("Optional search term to filter memories by content"),
|
|
518
621
|
category: zod.z.string().optional().describe('Optional category to filter by (e.g. "preference", "project", "personal")')
|
|
@@ -530,7 +633,7 @@ async function recallMemories(strapi, params, context) {
|
|
|
530
633
|
if (params.query) {
|
|
531
634
|
filters.content = { $containsi: params.query };
|
|
532
635
|
}
|
|
533
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
636
|
+
const memories = await strapi.documents(CONTENT_TYPE$9).findMany({
|
|
534
637
|
filters,
|
|
535
638
|
fields: ["content", "category"],
|
|
536
639
|
sort: { createdAt: "desc" }
|
|
@@ -556,7 +659,7 @@ const findOneContentSchema = zod.z.object({
|
|
|
556
659
|
status: zod.z.enum(["draft", "published"]).optional().describe("Document status filter."),
|
|
557
660
|
locale: zod.z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
558
661
|
});
|
|
559
|
-
const findOneContentDescription = "Fetch a single document by its documentId
|
|
662
|
+
const findOneContentDescription = "Fetch a single document by its exact documentId. Use this when you already have a documentId and need full details with populated relations. If you need to find documents by title, field values, or full-text search, use searchContent instead. Requires contentType and documentId.";
|
|
560
663
|
async function findOneContent(strapi, params) {
|
|
561
664
|
const { contentType, documentId, populate = "*", fields, status, locale } = params;
|
|
562
665
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -582,7 +685,7 @@ const uploadMediaSchema = zod.z.object({
|
|
|
582
685
|
caption: zod.z.string().optional().describe("Caption for the media file"),
|
|
583
686
|
alternativeText: zod.z.string().optional().describe("Alternative text for accessibility")
|
|
584
687
|
});
|
|
585
|
-
const uploadMediaDescription = "Upload a media file from a URL to the Strapi media library.
|
|
688
|
+
const uploadMediaDescription = "Upload a media file from a URL to the Strapi media library. This is step 1 of a two-step process: (1) upload the file with this tool to get a file ID, then (2) link it to a content entry using createContent or updateContent with { fieldName: fileId }. Requires url. Optional: name, caption, alternativeText.";
|
|
586
689
|
async function uploadMedia(strapi, params) {
|
|
587
690
|
const { url, name, caption, alternativeText } = params;
|
|
588
691
|
let parsedUrl;
|
|
@@ -653,7 +756,7 @@ async function uploadMedia(strapi, params) {
|
|
|
653
756
|
usage: `To link this file to a content type field, use createContent or updateContent with: { "fieldName": ${uploadedFile.id} }`
|
|
654
757
|
};
|
|
655
758
|
}
|
|
656
|
-
const CONTENT_TYPE$
|
|
759
|
+
const CONTENT_TYPE$8 = "plugin::ai-sdk.public-memory";
|
|
657
760
|
const recallPublicMemoriesSchema = zod.z.object({
|
|
658
761
|
query: zod.z.string().optional().describe("Optional search term to filter public memories by content"),
|
|
659
762
|
category: zod.z.string().optional().describe('Optional category to filter by (e.g. "faq", "product", "policy")')
|
|
@@ -664,7 +767,7 @@ async function recallPublicMemories(strapi, params) {
|
|
|
664
767
|
const filters = {};
|
|
665
768
|
if (params.category) filters.category = params.category;
|
|
666
769
|
if (params.query) filters.content = { $containsi: params.query };
|
|
667
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
770
|
+
const memories = await strapi.documents(CONTENT_TYPE$8).findMany({
|
|
668
771
|
filters,
|
|
669
772
|
fields: ["content", "category"],
|
|
670
773
|
sort: { createdAt: "desc" }
|
|
@@ -746,7 +849,7 @@ const aggregateContentSchema = zod.z.object({
|
|
|
746
849
|
status: zod.z.enum(["draft", "published"]).optional().describe("Filter by document status"),
|
|
747
850
|
locale: zod.z.string().optional().describe("Locale code for i18n content")
|
|
748
851
|
});
|
|
749
|
-
const aggregateContentDescription = '
|
|
852
|
+
const aggregateContentDescription = 'Count and group content entries for analytics. Answers questions like "how many articles?", "posts per category", "content published by month". Three operations: count (total), countByField (group by a field), countByDateRange (bucket by day/week/month). Prefer this over searchContent when you need counts or distributions, not the documents themselves.';
|
|
750
853
|
function buildBaseQuery(params) {
|
|
751
854
|
const { filters, status, locale, dateFrom, dateTo, dateField = "createdAt" } = params;
|
|
752
855
|
const query = {};
|
|
@@ -898,7 +1001,7 @@ async function aggregateContent(strapi, params) {
|
|
|
898
1001
|
throw new Error(`Unknown operation: ${operation}`);
|
|
899
1002
|
}
|
|
900
1003
|
}
|
|
901
|
-
const CONTENT_TYPE$
|
|
1004
|
+
const CONTENT_TYPE$7 = "plugin::ai-sdk.task";
|
|
902
1005
|
const manageTaskSchema = zod.z.object({
|
|
903
1006
|
action: zod.z.enum(["create", "update", "complete", "list", "summary"]).describe(
|
|
904
1007
|
"Action to perform: create a new task, update an existing task, complete (mark done), list open tasks, or get a summary."
|
|
@@ -914,14 +1017,14 @@ const manageTaskSchema = zod.z.object({
|
|
|
914
1017
|
done: zod.z.boolean().optional().describe("Set done status explicitly (for update action)."),
|
|
915
1018
|
filters: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Additional Strapi filters for list action.")
|
|
916
1019
|
});
|
|
917
|
-
const manageTaskDescription = "Manage the user's task list.
|
|
1020
|
+
const manageTaskDescription = "Manage the user's task list. Actions: create (new task), update (modify fields), complete (mark done), list (open tasks sorted by priority score), summary (overview with overdue/urgent counts). Tasks are scored by consequence × impact to prioritize what matters most. For create: title is required; consequence and impact are collected via UI form if omitted.";
|
|
918
1021
|
async function resolveTask(strapi, adminUserId, documentId, title) {
|
|
919
1022
|
if (documentId) {
|
|
920
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1023
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).findOne({ documentId });
|
|
921
1024
|
if (task2 && task2.adminUserId === adminUserId) return task2;
|
|
922
1025
|
}
|
|
923
1026
|
if (title) {
|
|
924
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1027
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
925
1028
|
filters: {
|
|
926
1029
|
adminUserId,
|
|
927
1030
|
title: { $containsi: title }
|
|
@@ -974,7 +1077,7 @@ async function manageTask(strapi, params, context) {
|
|
|
974
1077
|
if (params.consequence !== void 0) data.consequence = params.consequence;
|
|
975
1078
|
if (params.impact !== void 0) data.impact = params.impact;
|
|
976
1079
|
if (params.dueDate !== void 0) data.dueDate = params.dueDate;
|
|
977
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1080
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
978
1081
|
documentId: duplicate.documentId,
|
|
979
1082
|
data
|
|
980
1083
|
});
|
|
@@ -985,7 +1088,7 @@ async function manageTask(strapi, params, context) {
|
|
|
985
1088
|
data: updated
|
|
986
1089
|
};
|
|
987
1090
|
}
|
|
988
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1091
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).create({
|
|
989
1092
|
data: {
|
|
990
1093
|
title: params.title,
|
|
991
1094
|
description: params.description,
|
|
@@ -1014,7 +1117,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1014
1117
|
for (const key of ["title", "description", "content", "priority", "consequence", "impact", "dueDate", "done"]) {
|
|
1015
1118
|
if (params[key] !== void 0) data[key] = params[key];
|
|
1016
1119
|
}
|
|
1017
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1120
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
1018
1121
|
documentId: existing.documentId,
|
|
1019
1122
|
data
|
|
1020
1123
|
});
|
|
@@ -1025,7 +1128,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1025
1128
|
if (!toComplete) {
|
|
1026
1129
|
return { success: false, message: "Task not found. Provide a documentId or a title to search by." };
|
|
1027
1130
|
}
|
|
1028
|
-
await strapi.documents(CONTENT_TYPE$
|
|
1131
|
+
await strapi.documents(CONTENT_TYPE$7).update({
|
|
1029
1132
|
documentId: toComplete.documentId,
|
|
1030
1133
|
data: { done: true }
|
|
1031
1134
|
});
|
|
@@ -1037,7 +1140,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1037
1140
|
done: false,
|
|
1038
1141
|
...params.filters
|
|
1039
1142
|
};
|
|
1040
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1143
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1041
1144
|
filters
|
|
1042
1145
|
});
|
|
1043
1146
|
const sorted = tasks.sort((a, b) => {
|
|
@@ -1066,7 +1169,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1066
1169
|
};
|
|
1067
1170
|
}
|
|
1068
1171
|
case "summary": {
|
|
1069
|
-
const allOpen = await strapi.documents(CONTENT_TYPE$
|
|
1172
|
+
const allOpen = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1070
1173
|
filters: { adminUserId, done: false }
|
|
1071
1174
|
});
|
|
1072
1175
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -1103,6 +1206,82 @@ async function manageTask(strapi, params, context) {
|
|
|
1103
1206
|
return { success: false, message: `Task operation failed: ${detail}` };
|
|
1104
1207
|
}
|
|
1105
1208
|
}
|
|
1209
|
+
const CONTENT_TYPE$6 = "plugin::ai-sdk.note";
|
|
1210
|
+
const saveNoteSchema = zod.z.object({
|
|
1211
|
+
title: zod.z.string().optional().describe("A short title or label for the note"),
|
|
1212
|
+
content: zod.z.string().describe("The note content in markdown format. Can include code blocks, lists, links, etc."),
|
|
1213
|
+
category: zod.z.string().optional().describe('Category for the note: "research", "snippet", "idea", or "reference". Defaults to "research".'),
|
|
1214
|
+
tags: zod.z.string().optional().describe('Comma-separated tags for filtering (e.g. "strapi, api, tutorial")'),
|
|
1215
|
+
source: zod.z.string().optional().describe('Where this note came from (e.g. "conversation", "web research", a URL)')
|
|
1216
|
+
});
|
|
1217
|
+
const saveNoteDescription = "Save a research note, code snippet, idea, or reference for the user. Use this when the user wants to save part of a conversation, research findings, code examples, or any content they may want to use later for writing blog posts or articles. Content is saved as markdown.";
|
|
1218
|
+
async function saveNote(strapi, params, context) {
|
|
1219
|
+
if (!context?.adminUserId) {
|
|
1220
|
+
return { success: false, message: "Cannot save note: user context not available." };
|
|
1221
|
+
}
|
|
1222
|
+
try {
|
|
1223
|
+
await strapi.documents(CONTENT_TYPE$6).create({
|
|
1224
|
+
data: {
|
|
1225
|
+
title: params.title || "",
|
|
1226
|
+
content: params.content,
|
|
1227
|
+
category: params.category || "research",
|
|
1228
|
+
tags: params.tags || "",
|
|
1229
|
+
source: params.source || "conversation",
|
|
1230
|
+
adminUserId: context.adminUserId
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
const label = params.title ? `"${params.title}"` : "Note";
|
|
1234
|
+
return { success: true, message: `${label} saved to research notes.` };
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1237
|
+
return { success: false, message: `Failed to save note: ${detail}` };
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
const CONTENT_TYPE$5 = "plugin::ai-sdk.note";
|
|
1241
|
+
const recallNotesSchema = zod.z.object({
|
|
1242
|
+
query: zod.z.string().optional().describe("Optional search term to filter notes by title or content"),
|
|
1243
|
+
category: zod.z.string().optional().describe('Optional category to filter by: "research", "snippet", "idea", "reference"'),
|
|
1244
|
+
tag: zod.z.string().optional().describe("Optional tag to filter by (matches within comma-separated tags)")
|
|
1245
|
+
});
|
|
1246
|
+
const recallNotesDescription = "Recall saved research notes, snippets, ideas, and references. Use this to look up previously saved notes. Without parameters, returns all notes.";
|
|
1247
|
+
async function recallNotes(strapi, params, context) {
|
|
1248
|
+
if (!context?.adminUserId) {
|
|
1249
|
+
return { success: false, notes: [], count: 0 };
|
|
1250
|
+
}
|
|
1251
|
+
try {
|
|
1252
|
+
const filters = { adminUserId: context.adminUserId };
|
|
1253
|
+
if (params.category) {
|
|
1254
|
+
filters.category = params.category;
|
|
1255
|
+
}
|
|
1256
|
+
if (params.query) {
|
|
1257
|
+
filters.$or = [
|
|
1258
|
+
{ title: { $containsi: params.query } },
|
|
1259
|
+
{ content: { $containsi: params.query } }
|
|
1260
|
+
];
|
|
1261
|
+
}
|
|
1262
|
+
if (params.tag) {
|
|
1263
|
+
filters.tags = { $containsi: params.tag };
|
|
1264
|
+
}
|
|
1265
|
+
const notes = await strapi.documents(CONTENT_TYPE$5).findMany({
|
|
1266
|
+
filters,
|
|
1267
|
+
fields: ["title", "content", "category", "tags", "source"],
|
|
1268
|
+
sort: { createdAt: "desc" }
|
|
1269
|
+
});
|
|
1270
|
+
return {
|
|
1271
|
+
success: true,
|
|
1272
|
+
notes: notes.map((n) => ({
|
|
1273
|
+
title: n.title || "",
|
|
1274
|
+
content: n.content,
|
|
1275
|
+
category: n.category,
|
|
1276
|
+
tags: n.tags || "",
|
|
1277
|
+
source: n.source || ""
|
|
1278
|
+
})),
|
|
1279
|
+
count: notes.length
|
|
1280
|
+
};
|
|
1281
|
+
} catch (error) {
|
|
1282
|
+
return { success: false, notes: [], count: 0 };
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1106
1285
|
const listContentTypesTool = {
|
|
1107
1286
|
name: "listContentTypes",
|
|
1108
1287
|
description: listContentTypesDescription,
|
|
@@ -1233,6 +1412,20 @@ const manageTaskTool = {
|
|
|
1233
1412
|
execute: async (args, strapi, context) => manageTask(strapi, args, context),
|
|
1234
1413
|
internal: true
|
|
1235
1414
|
};
|
|
1415
|
+
const saveNoteTool = {
|
|
1416
|
+
name: "saveNote",
|
|
1417
|
+
description: saveNoteDescription,
|
|
1418
|
+
schema: saveNoteSchema,
|
|
1419
|
+
execute: async (args, strapi, context) => saveNote(strapi, args, context),
|
|
1420
|
+
internal: true
|
|
1421
|
+
};
|
|
1422
|
+
const recallNotesTool = {
|
|
1423
|
+
name: "recallNotes",
|
|
1424
|
+
description: recallNotesDescription,
|
|
1425
|
+
schema: recallNotesSchema,
|
|
1426
|
+
execute: async (args, strapi, context) => recallNotes(strapi, args, context),
|
|
1427
|
+
internal: true
|
|
1428
|
+
};
|
|
1236
1429
|
const builtInTools = [
|
|
1237
1430
|
listContentTypesTool,
|
|
1238
1431
|
searchContentTool,
|
|
@@ -1245,7 +1438,9 @@ const builtInTools = [
|
|
|
1245
1438
|
recallMemoriesTool,
|
|
1246
1439
|
recallPublicMemoriesTool,
|
|
1247
1440
|
aggregateContentTool,
|
|
1248
|
-
manageTaskTool
|
|
1441
|
+
manageTaskTool,
|
|
1442
|
+
saveNoteTool,
|
|
1443
|
+
recallNotesTool
|
|
1249
1444
|
];
|
|
1250
1445
|
const PLUGIN_ID$2 = "ai-sdk";
|
|
1251
1446
|
const bootstrap = ({ strapi }) => {
|
|
@@ -1416,17 +1611,17 @@ const config = {
|
|
|
1416
1611
|
}
|
|
1417
1612
|
}
|
|
1418
1613
|
};
|
|
1419
|
-
const kind$
|
|
1420
|
-
const collectionName$
|
|
1421
|
-
const info$
|
|
1614
|
+
const kind$4 = "collectionType";
|
|
1615
|
+
const collectionName$4 = "ai_sdk_conversations";
|
|
1616
|
+
const info$4 = {
|
|
1422
1617
|
singularName: "conversation",
|
|
1423
1618
|
pluralName: "conversations",
|
|
1424
1619
|
displayName: "AI Conversation"
|
|
1425
1620
|
};
|
|
1426
|
-
const options$
|
|
1621
|
+
const options$4 = {
|
|
1427
1622
|
draftAndPublish: false
|
|
1428
1623
|
};
|
|
1429
|
-
const pluginOptions$
|
|
1624
|
+
const pluginOptions$4 = {
|
|
1430
1625
|
"content-manager": {
|
|
1431
1626
|
visible: false
|
|
1432
1627
|
},
|
|
@@ -1434,7 +1629,7 @@ const pluginOptions$3 = {
|
|
|
1434
1629
|
visible: false
|
|
1435
1630
|
}
|
|
1436
1631
|
};
|
|
1437
|
-
const attributes$
|
|
1632
|
+
const attributes$4 = {
|
|
1438
1633
|
title: {
|
|
1439
1634
|
type: "string",
|
|
1440
1635
|
required: true,
|
|
@@ -1449,26 +1644,26 @@ const attributes$3 = {
|
|
|
1449
1644
|
required: true
|
|
1450
1645
|
}
|
|
1451
1646
|
};
|
|
1452
|
-
const schema$
|
|
1453
|
-
kind: kind$
|
|
1454
|
-
collectionName: collectionName$
|
|
1455
|
-
info: info$
|
|
1456
|
-
options: options$
|
|
1457
|
-
pluginOptions: pluginOptions$
|
|
1458
|
-
attributes: attributes$
|
|
1647
|
+
const schema$4 = {
|
|
1648
|
+
kind: kind$4,
|
|
1649
|
+
collectionName: collectionName$4,
|
|
1650
|
+
info: info$4,
|
|
1651
|
+
options: options$4,
|
|
1652
|
+
pluginOptions: pluginOptions$4,
|
|
1653
|
+
attributes: attributes$4
|
|
1459
1654
|
};
|
|
1460
|
-
const conversation = { schema: schema$
|
|
1461
|
-
const kind$
|
|
1462
|
-
const collectionName$
|
|
1463
|
-
const info$
|
|
1655
|
+
const conversation = { schema: schema$4 };
|
|
1656
|
+
const kind$3 = "collectionType";
|
|
1657
|
+
const collectionName$3 = "ai_sdk_memories";
|
|
1658
|
+
const info$3 = {
|
|
1464
1659
|
singularName: "memory",
|
|
1465
1660
|
pluralName: "memories",
|
|
1466
1661
|
displayName: "AI Memory"
|
|
1467
1662
|
};
|
|
1468
|
-
const options$
|
|
1663
|
+
const options$3 = {
|
|
1469
1664
|
draftAndPublish: false
|
|
1470
1665
|
};
|
|
1471
|
-
const pluginOptions$
|
|
1666
|
+
const pluginOptions$3 = {
|
|
1472
1667
|
"content-manager": {
|
|
1473
1668
|
visible: false
|
|
1474
1669
|
},
|
|
@@ -1476,9 +1671,9 @@ const pluginOptions$2 = {
|
|
|
1476
1671
|
visible: false
|
|
1477
1672
|
}
|
|
1478
1673
|
};
|
|
1479
|
-
const attributes$
|
|
1674
|
+
const attributes$3 = {
|
|
1480
1675
|
content: {
|
|
1481
|
-
type: "
|
|
1676
|
+
type: "richtext",
|
|
1482
1677
|
required: true
|
|
1483
1678
|
},
|
|
1484
1679
|
category: {
|
|
@@ -1496,26 +1691,26 @@ const attributes$2 = {
|
|
|
1496
1691
|
required: true
|
|
1497
1692
|
}
|
|
1498
1693
|
};
|
|
1499
|
-
const schema$
|
|
1500
|
-
kind: kind$
|
|
1501
|
-
collectionName: collectionName$
|
|
1502
|
-
info: info$
|
|
1503
|
-
options: options$
|
|
1504
|
-
pluginOptions: pluginOptions$
|
|
1505
|
-
attributes: attributes$
|
|
1694
|
+
const schema$3 = {
|
|
1695
|
+
kind: kind$3,
|
|
1696
|
+
collectionName: collectionName$3,
|
|
1697
|
+
info: info$3,
|
|
1698
|
+
options: options$3,
|
|
1699
|
+
pluginOptions: pluginOptions$3,
|
|
1700
|
+
attributes: attributes$3
|
|
1506
1701
|
};
|
|
1507
|
-
const memory = { schema: schema$
|
|
1508
|
-
const kind$
|
|
1509
|
-
const collectionName$
|
|
1510
|
-
const info$
|
|
1702
|
+
const memory = { schema: schema$3 };
|
|
1703
|
+
const kind$2 = "collectionType";
|
|
1704
|
+
const collectionName$2 = "ai_sdk_public_memories";
|
|
1705
|
+
const info$2 = {
|
|
1511
1706
|
singularName: "public-memory",
|
|
1512
1707
|
pluralName: "public-memories",
|
|
1513
1708
|
displayName: "AI Public Memory"
|
|
1514
1709
|
};
|
|
1515
|
-
const options$
|
|
1710
|
+
const options$2 = {
|
|
1516
1711
|
draftAndPublish: false
|
|
1517
1712
|
};
|
|
1518
|
-
const pluginOptions$
|
|
1713
|
+
const pluginOptions$2 = {
|
|
1519
1714
|
"content-manager": {
|
|
1520
1715
|
visible: false
|
|
1521
1716
|
},
|
|
@@ -1523,7 +1718,7 @@ const pluginOptions$1 = {
|
|
|
1523
1718
|
visible: false
|
|
1524
1719
|
}
|
|
1525
1720
|
};
|
|
1526
|
-
const attributes$
|
|
1721
|
+
const attributes$2 = {
|
|
1527
1722
|
content: {
|
|
1528
1723
|
type: "text",
|
|
1529
1724
|
required: true
|
|
@@ -1539,26 +1734,26 @@ const attributes$1 = {
|
|
|
1539
1734
|
"default": "general"
|
|
1540
1735
|
}
|
|
1541
1736
|
};
|
|
1542
|
-
const schema$
|
|
1543
|
-
kind: kind$
|
|
1544
|
-
collectionName: collectionName$
|
|
1545
|
-
info: info$
|
|
1546
|
-
options: options$
|
|
1547
|
-
pluginOptions: pluginOptions$
|
|
1548
|
-
attributes: attributes$
|
|
1737
|
+
const schema$2 = {
|
|
1738
|
+
kind: kind$2,
|
|
1739
|
+
collectionName: collectionName$2,
|
|
1740
|
+
info: info$2,
|
|
1741
|
+
options: options$2,
|
|
1742
|
+
pluginOptions: pluginOptions$2,
|
|
1743
|
+
attributes: attributes$2
|
|
1549
1744
|
};
|
|
1550
|
-
const publicMemory = { schema: schema$
|
|
1551
|
-
const kind = "collectionType";
|
|
1552
|
-
const collectionName = "ai_sdk_tasks";
|
|
1553
|
-
const info = {
|
|
1745
|
+
const publicMemory = { schema: schema$2 };
|
|
1746
|
+
const kind$1 = "collectionType";
|
|
1747
|
+
const collectionName$1 = "ai_sdk_tasks";
|
|
1748
|
+
const info$1 = {
|
|
1554
1749
|
singularName: "task",
|
|
1555
1750
|
pluralName: "tasks",
|
|
1556
1751
|
displayName: "AI Task"
|
|
1557
1752
|
};
|
|
1558
|
-
const options = {
|
|
1753
|
+
const options$1 = {
|
|
1559
1754
|
draftAndPublish: false
|
|
1560
1755
|
};
|
|
1561
|
-
const pluginOptions = {
|
|
1756
|
+
const pluginOptions$1 = {
|
|
1562
1757
|
"content-manager": {
|
|
1563
1758
|
visible: true
|
|
1564
1759
|
},
|
|
@@ -1566,7 +1761,7 @@ const pluginOptions = {
|
|
|
1566
1761
|
visible: false
|
|
1567
1762
|
}
|
|
1568
1763
|
};
|
|
1569
|
-
const attributes = {
|
|
1764
|
+
const attributes$1 = {
|
|
1570
1765
|
title: {
|
|
1571
1766
|
type: "string",
|
|
1572
1767
|
required: true
|
|
@@ -1611,6 +1806,62 @@ const attributes = {
|
|
|
1611
1806
|
required: true
|
|
1612
1807
|
}
|
|
1613
1808
|
};
|
|
1809
|
+
const schema$1 = {
|
|
1810
|
+
kind: kind$1,
|
|
1811
|
+
collectionName: collectionName$1,
|
|
1812
|
+
info: info$1,
|
|
1813
|
+
options: options$1,
|
|
1814
|
+
pluginOptions: pluginOptions$1,
|
|
1815
|
+
attributes: attributes$1
|
|
1816
|
+
};
|
|
1817
|
+
const task = { schema: schema$1 };
|
|
1818
|
+
const kind = "collectionType";
|
|
1819
|
+
const collectionName = "ai_sdk_notes";
|
|
1820
|
+
const info = {
|
|
1821
|
+
singularName: "note",
|
|
1822
|
+
pluralName: "notes",
|
|
1823
|
+
displayName: "AI Note"
|
|
1824
|
+
};
|
|
1825
|
+
const options = {
|
|
1826
|
+
draftAndPublish: false
|
|
1827
|
+
};
|
|
1828
|
+
const pluginOptions = {
|
|
1829
|
+
"content-manager": {
|
|
1830
|
+
visible: false
|
|
1831
|
+
},
|
|
1832
|
+
"content-type-builder": {
|
|
1833
|
+
visible: false
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
const attributes = {
|
|
1837
|
+
title: {
|
|
1838
|
+
type: "string"
|
|
1839
|
+
},
|
|
1840
|
+
content: {
|
|
1841
|
+
type: "richtext",
|
|
1842
|
+
required: true
|
|
1843
|
+
},
|
|
1844
|
+
category: {
|
|
1845
|
+
type: "enumeration",
|
|
1846
|
+
"enum": [
|
|
1847
|
+
"research",
|
|
1848
|
+
"snippet",
|
|
1849
|
+
"idea",
|
|
1850
|
+
"reference"
|
|
1851
|
+
],
|
|
1852
|
+
"default": "research"
|
|
1853
|
+
},
|
|
1854
|
+
tags: {
|
|
1855
|
+
type: "text"
|
|
1856
|
+
},
|
|
1857
|
+
source: {
|
|
1858
|
+
type: "string"
|
|
1859
|
+
},
|
|
1860
|
+
adminUserId: {
|
|
1861
|
+
type: "integer",
|
|
1862
|
+
required: true
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1614
1865
|
const schema = {
|
|
1615
1866
|
kind,
|
|
1616
1867
|
collectionName,
|
|
@@ -1619,8 +1870,8 @@ const schema = {
|
|
|
1619
1870
|
pluginOptions,
|
|
1620
1871
|
attributes
|
|
1621
1872
|
};
|
|
1622
|
-
const
|
|
1623
|
-
const contentTypes = { conversation, memory, "public-memory": publicMemory, task };
|
|
1873
|
+
const note = { schema };
|
|
1874
|
+
const contentTypes = { conversation, memory, "public-memory": publicMemory, task, note };
|
|
1624
1875
|
function getService(strapi, ctx) {
|
|
1625
1876
|
const service2 = strapi.plugin("ai-sdk").service("service");
|
|
1626
1877
|
if (!service2.isInitialized()) {
|
|
@@ -1936,20 +2187,20 @@ const mcpController = ({ strapi }) => {
|
|
|
1936
2187
|
}
|
|
1937
2188
|
};
|
|
1938
2189
|
};
|
|
1939
|
-
const CONTENT_TYPE$
|
|
1940
|
-
function getAdminUserId$
|
|
2190
|
+
const CONTENT_TYPE$4 = "plugin::ai-sdk.conversation";
|
|
2191
|
+
function getAdminUserId$3(ctx) {
|
|
1941
2192
|
const id = ctx.state?.user?.id;
|
|
1942
2193
|
return typeof id === "number" ? id : null;
|
|
1943
2194
|
}
|
|
1944
2195
|
const conversationController = ({ strapi }) => ({
|
|
1945
2196
|
async find(ctx) {
|
|
1946
|
-
const adminUserId = getAdminUserId$
|
|
2197
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1947
2198
|
if (!adminUserId) {
|
|
1948
2199
|
ctx.status = 401;
|
|
1949
2200
|
ctx.body = { error: "Unauthorized" };
|
|
1950
2201
|
return;
|
|
1951
2202
|
}
|
|
1952
|
-
const conversations = await strapi.documents(CONTENT_TYPE$
|
|
2203
|
+
const conversations = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
1953
2204
|
filters: { adminUserId },
|
|
1954
2205
|
fields: ["title", "createdAt", "updatedAt"],
|
|
1955
2206
|
sort: { updatedAt: "desc" }
|
|
@@ -1957,14 +2208,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1957
2208
|
ctx.body = { data: conversations };
|
|
1958
2209
|
},
|
|
1959
2210
|
async findOne(ctx) {
|
|
1960
|
-
const adminUserId = getAdminUserId$
|
|
2211
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1961
2212
|
if (!adminUserId) {
|
|
1962
2213
|
ctx.status = 401;
|
|
1963
2214
|
ctx.body = { error: "Unauthorized" };
|
|
1964
2215
|
return;
|
|
1965
2216
|
}
|
|
1966
2217
|
const { id } = ctx.params;
|
|
1967
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2218
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1968
2219
|
documentId: id
|
|
1969
2220
|
});
|
|
1970
2221
|
if (!conversation2 || conversation2.adminUserId !== adminUserId) {
|
|
@@ -1975,14 +2226,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1975
2226
|
ctx.body = { data: conversation2 };
|
|
1976
2227
|
},
|
|
1977
2228
|
async create(ctx) {
|
|
1978
|
-
const adminUserId = getAdminUserId$
|
|
2229
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1979
2230
|
if (!adminUserId) {
|
|
1980
2231
|
ctx.status = 401;
|
|
1981
2232
|
ctx.body = { error: "Unauthorized" };
|
|
1982
2233
|
return;
|
|
1983
2234
|
}
|
|
1984
2235
|
const { title, messages } = ctx.request.body;
|
|
1985
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2236
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).create({
|
|
1986
2237
|
data: {
|
|
1987
2238
|
title: title || "New conversation",
|
|
1988
2239
|
messages: messages || [],
|
|
@@ -1993,14 +2244,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1993
2244
|
ctx.body = { data: conversation2 };
|
|
1994
2245
|
},
|
|
1995
2246
|
async update(ctx) {
|
|
1996
|
-
const adminUserId = getAdminUserId$
|
|
2247
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1997
2248
|
if (!adminUserId) {
|
|
1998
2249
|
ctx.status = 401;
|
|
1999
2250
|
ctx.body = { error: "Unauthorized" };
|
|
2000
2251
|
return;
|
|
2001
2252
|
}
|
|
2002
2253
|
const { id } = ctx.params;
|
|
2003
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2254
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
2004
2255
|
documentId: id
|
|
2005
2256
|
});
|
|
2006
2257
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2012,21 +2263,21 @@ const conversationController = ({ strapi }) => ({
|
|
|
2012
2263
|
const data = {};
|
|
2013
2264
|
if (title !== void 0) data.title = title;
|
|
2014
2265
|
if (messages !== void 0) data.messages = messages;
|
|
2015
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2266
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).update({
|
|
2016
2267
|
documentId: id,
|
|
2017
2268
|
data
|
|
2018
2269
|
});
|
|
2019
2270
|
ctx.body = { data: conversation2 };
|
|
2020
2271
|
},
|
|
2021
2272
|
async delete(ctx) {
|
|
2022
|
-
const adminUserId = getAdminUserId$
|
|
2273
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
2023
2274
|
if (!adminUserId) {
|
|
2024
2275
|
ctx.status = 401;
|
|
2025
2276
|
ctx.body = { error: "Unauthorized" };
|
|
2026
2277
|
return;
|
|
2027
2278
|
}
|
|
2028
2279
|
const { id } = ctx.params;
|
|
2029
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2280
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
2030
2281
|
documentId: id
|
|
2031
2282
|
});
|
|
2032
2283
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2034,25 +2285,25 @@ const conversationController = ({ strapi }) => ({
|
|
|
2034
2285
|
ctx.body = { error: "Conversation not found" };
|
|
2035
2286
|
return;
|
|
2036
2287
|
}
|
|
2037
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2288
|
+
await strapi.documents(CONTENT_TYPE$4).delete({ documentId: id });
|
|
2038
2289
|
ctx.status = 200;
|
|
2039
2290
|
ctx.body = { data: { documentId: id } };
|
|
2040
2291
|
}
|
|
2041
2292
|
});
|
|
2042
|
-
const CONTENT_TYPE$
|
|
2043
|
-
function getAdminUserId$
|
|
2293
|
+
const CONTENT_TYPE$3 = "plugin::ai-sdk.memory";
|
|
2294
|
+
function getAdminUserId$2(ctx) {
|
|
2044
2295
|
const id = ctx.state?.user?.id;
|
|
2045
2296
|
return typeof id === "number" ? id : null;
|
|
2046
2297
|
}
|
|
2047
2298
|
const memoryController = ({ strapi }) => ({
|
|
2048
2299
|
async find(ctx) {
|
|
2049
|
-
const adminUserId = getAdminUserId$
|
|
2300
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2050
2301
|
if (!adminUserId) {
|
|
2051
2302
|
ctx.status = 401;
|
|
2052
2303
|
ctx.body = { error: "Unauthorized" };
|
|
2053
2304
|
return;
|
|
2054
2305
|
}
|
|
2055
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2306
|
+
const memories = await strapi.documents(CONTENT_TYPE$3).findMany({
|
|
2056
2307
|
filters: { adminUserId },
|
|
2057
2308
|
fields: ["content", "category", "createdAt"],
|
|
2058
2309
|
sort: { createdAt: "desc" }
|
|
@@ -2060,7 +2311,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2060
2311
|
ctx.body = { data: memories };
|
|
2061
2312
|
},
|
|
2062
2313
|
async create(ctx) {
|
|
2063
|
-
const adminUserId = getAdminUserId$
|
|
2314
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2064
2315
|
if (!adminUserId) {
|
|
2065
2316
|
ctx.status = 401;
|
|
2066
2317
|
ctx.body = { error: "Unauthorized" };
|
|
@@ -2072,7 +2323,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2072
2323
|
ctx.body = { error: "content is required" };
|
|
2073
2324
|
return;
|
|
2074
2325
|
}
|
|
2075
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2326
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).create({
|
|
2076
2327
|
data: {
|
|
2077
2328
|
content,
|
|
2078
2329
|
category: category || "general",
|
|
@@ -2083,14 +2334,14 @@ const memoryController = ({ strapi }) => ({
|
|
|
2083
2334
|
ctx.body = { data: memory2 };
|
|
2084
2335
|
},
|
|
2085
2336
|
async update(ctx) {
|
|
2086
|
-
const adminUserId = getAdminUserId$
|
|
2337
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2087
2338
|
if (!adminUserId) {
|
|
2088
2339
|
ctx.status = 401;
|
|
2089
2340
|
ctx.body = { error: "Unauthorized" };
|
|
2090
2341
|
return;
|
|
2091
2342
|
}
|
|
2092
2343
|
const { id } = ctx.params;
|
|
2093
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2344
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2094
2345
|
documentId: id
|
|
2095
2346
|
});
|
|
2096
2347
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2102,21 +2353,21 @@ const memoryController = ({ strapi }) => ({
|
|
|
2102
2353
|
const data = {};
|
|
2103
2354
|
if (content !== void 0) data.content = content;
|
|
2104
2355
|
if (category !== void 0) data.category = category;
|
|
2105
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2356
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).update({
|
|
2106
2357
|
documentId: id,
|
|
2107
2358
|
data
|
|
2108
2359
|
});
|
|
2109
2360
|
ctx.body = { data: memory2 };
|
|
2110
2361
|
},
|
|
2111
2362
|
async delete(ctx) {
|
|
2112
|
-
const adminUserId = getAdminUserId$
|
|
2363
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2113
2364
|
if (!adminUserId) {
|
|
2114
2365
|
ctx.status = 401;
|
|
2115
2366
|
ctx.body = { error: "Unauthorized" };
|
|
2116
2367
|
return;
|
|
2117
2368
|
}
|
|
2118
2369
|
const { id } = ctx.params;
|
|
2119
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2370
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2120
2371
|
documentId: id
|
|
2121
2372
|
});
|
|
2122
2373
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2124,15 +2375,15 @@ const memoryController = ({ strapi }) => ({
|
|
|
2124
2375
|
ctx.body = { error: "Memory not found" };
|
|
2125
2376
|
return;
|
|
2126
2377
|
}
|
|
2127
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2378
|
+
await strapi.documents(CONTENT_TYPE$3).delete({ documentId: id });
|
|
2128
2379
|
ctx.status = 200;
|
|
2129
2380
|
ctx.body = { data: { documentId: id } };
|
|
2130
2381
|
}
|
|
2131
2382
|
});
|
|
2132
|
-
const CONTENT_TYPE$
|
|
2383
|
+
const CONTENT_TYPE$2 = "plugin::ai-sdk.public-memory";
|
|
2133
2384
|
const publicMemoryController = ({ strapi }) => ({
|
|
2134
2385
|
async find(ctx) {
|
|
2135
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2386
|
+
const memories = await strapi.documents(CONTENT_TYPE$2).findMany({
|
|
2136
2387
|
fields: ["content", "category", "createdAt"],
|
|
2137
2388
|
sort: { createdAt: "desc" }
|
|
2138
2389
|
});
|
|
@@ -2145,7 +2396,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2145
2396
|
ctx.body = { error: "content is required" };
|
|
2146
2397
|
return;
|
|
2147
2398
|
}
|
|
2148
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2399
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).create({
|
|
2149
2400
|
data: { content, category: category || "general" }
|
|
2150
2401
|
});
|
|
2151
2402
|
ctx.status = 201;
|
|
@@ -2153,7 +2404,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2153
2404
|
},
|
|
2154
2405
|
async update(ctx) {
|
|
2155
2406
|
const { id } = ctx.params;
|
|
2156
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2407
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2157
2408
|
if (!existing) {
|
|
2158
2409
|
ctx.status = 404;
|
|
2159
2410
|
ctx.body = { error: "Public memory not found" };
|
|
@@ -2163,7 +2414,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2163
2414
|
const data = {};
|
|
2164
2415
|
if (content !== void 0) data.content = content;
|
|
2165
2416
|
if (category !== void 0) data.category = category;
|
|
2166
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2417
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).update({
|
|
2167
2418
|
documentId: id,
|
|
2168
2419
|
data
|
|
2169
2420
|
});
|
|
@@ -2171,45 +2422,45 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2171
2422
|
},
|
|
2172
2423
|
async delete(ctx) {
|
|
2173
2424
|
const { id } = ctx.params;
|
|
2174
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2425
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2175
2426
|
if (!existing) {
|
|
2176
2427
|
ctx.status = 404;
|
|
2177
2428
|
ctx.body = { error: "Public memory not found" };
|
|
2178
2429
|
return;
|
|
2179
2430
|
}
|
|
2180
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2431
|
+
await strapi.documents(CONTENT_TYPE$2).delete({ documentId: id });
|
|
2181
2432
|
ctx.status = 200;
|
|
2182
2433
|
ctx.body = { data: { documentId: id } };
|
|
2183
2434
|
}
|
|
2184
2435
|
});
|
|
2185
|
-
const CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
2186
|
-
function getAdminUserId(ctx) {
|
|
2436
|
+
const CONTENT_TYPE$1 = "plugin::ai-sdk.task";
|
|
2437
|
+
function getAdminUserId$1(ctx) {
|
|
2187
2438
|
const id = ctx.state?.user?.id;
|
|
2188
2439
|
return typeof id === "number" ? id : null;
|
|
2189
2440
|
}
|
|
2190
2441
|
const taskController = ({ strapi }) => ({
|
|
2191
2442
|
async find(ctx) {
|
|
2192
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2443
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2193
2444
|
if (!adminUserId) {
|
|
2194
2445
|
ctx.status = 401;
|
|
2195
2446
|
ctx.body = { error: "Unauthorized" };
|
|
2196
2447
|
return;
|
|
2197
2448
|
}
|
|
2198
|
-
const tasks = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2449
|
+
const tasks = await strapi.documents(CONTENT_TYPE$1).findMany({
|
|
2199
2450
|
filters: { adminUserId },
|
|
2200
2451
|
sort: { createdAt: "desc" }
|
|
2201
2452
|
});
|
|
2202
2453
|
ctx.body = { data: tasks };
|
|
2203
2454
|
},
|
|
2204
2455
|
async create(ctx) {
|
|
2205
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2456
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2206
2457
|
if (!adminUserId) {
|
|
2207
2458
|
ctx.status = 401;
|
|
2208
2459
|
ctx.body = { error: "Unauthorized" };
|
|
2209
2460
|
return;
|
|
2210
2461
|
}
|
|
2211
2462
|
const body = ctx.request.body;
|
|
2212
|
-
const task2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2463
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).create({
|
|
2213
2464
|
data: {
|
|
2214
2465
|
title: body.title,
|
|
2215
2466
|
description: body.description,
|
|
@@ -2226,14 +2477,14 @@ const taskController = ({ strapi }) => ({
|
|
|
2226
2477
|
ctx.body = { data: task2 };
|
|
2227
2478
|
},
|
|
2228
2479
|
async update(ctx) {
|
|
2229
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2480
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2230
2481
|
if (!adminUserId) {
|
|
2231
2482
|
ctx.status = 401;
|
|
2232
2483
|
ctx.body = { error: "Unauthorized" };
|
|
2233
2484
|
return;
|
|
2234
2485
|
}
|
|
2235
2486
|
const { id } = ctx.params;
|
|
2236
|
-
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2487
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({
|
|
2237
2488
|
documentId: id
|
|
2238
2489
|
});
|
|
2239
2490
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2246,13 +2497,80 @@ const taskController = ({ strapi }) => ({
|
|
|
2246
2497
|
for (const key of ["title", "description", "content", "done", "priority", "consequence", "impact", "dueDate"]) {
|
|
2247
2498
|
if (body[key] !== void 0) data[key] = body[key];
|
|
2248
2499
|
}
|
|
2249
|
-
const task2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2500
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).update({
|
|
2250
2501
|
documentId: id,
|
|
2251
2502
|
data
|
|
2252
2503
|
});
|
|
2253
2504
|
ctx.body = { data: task2 };
|
|
2254
2505
|
},
|
|
2255
2506
|
async delete(ctx) {
|
|
2507
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2508
|
+
if (!adminUserId) {
|
|
2509
|
+
ctx.status = 401;
|
|
2510
|
+
ctx.body = { error: "Unauthorized" };
|
|
2511
|
+
return;
|
|
2512
|
+
}
|
|
2513
|
+
const { id } = ctx.params;
|
|
2514
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({
|
|
2515
|
+
documentId: id
|
|
2516
|
+
});
|
|
2517
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2518
|
+
ctx.status = 404;
|
|
2519
|
+
ctx.body = { error: "Task not found" };
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
await strapi.documents(CONTENT_TYPE$1).delete({ documentId: id });
|
|
2523
|
+
ctx.status = 200;
|
|
2524
|
+
ctx.body = { data: { documentId: id } };
|
|
2525
|
+
}
|
|
2526
|
+
});
|
|
2527
|
+
const CONTENT_TYPE = "plugin::ai-sdk.note";
|
|
2528
|
+
function getAdminUserId(ctx) {
|
|
2529
|
+
const id = ctx.state?.user?.id;
|
|
2530
|
+
return typeof id === "number" ? id : null;
|
|
2531
|
+
}
|
|
2532
|
+
const noteController = ({ strapi }) => ({
|
|
2533
|
+
async find(ctx) {
|
|
2534
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2535
|
+
if (!adminUserId) {
|
|
2536
|
+
ctx.status = 401;
|
|
2537
|
+
ctx.body = { error: "Unauthorized" };
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
const notes = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2541
|
+
filters: { adminUserId },
|
|
2542
|
+
fields: ["title", "content", "category", "tags", "source", "createdAt"],
|
|
2543
|
+
sort: { createdAt: "desc" }
|
|
2544
|
+
});
|
|
2545
|
+
ctx.body = { data: notes };
|
|
2546
|
+
},
|
|
2547
|
+
async create(ctx) {
|
|
2548
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2549
|
+
if (!adminUserId) {
|
|
2550
|
+
ctx.status = 401;
|
|
2551
|
+
ctx.body = { error: "Unauthorized" };
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
const { title, content, category, tags, source } = ctx.request.body;
|
|
2555
|
+
if (!content || typeof content !== "string") {
|
|
2556
|
+
ctx.status = 400;
|
|
2557
|
+
ctx.body = { error: "content is required" };
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
const note2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2561
|
+
data: {
|
|
2562
|
+
title: title || "",
|
|
2563
|
+
content,
|
|
2564
|
+
category: category || "research",
|
|
2565
|
+
tags: tags || "",
|
|
2566
|
+
source: source || "",
|
|
2567
|
+
adminUserId
|
|
2568
|
+
}
|
|
2569
|
+
});
|
|
2570
|
+
ctx.status = 201;
|
|
2571
|
+
ctx.body = { data: note2 };
|
|
2572
|
+
},
|
|
2573
|
+
async update(ctx) {
|
|
2256
2574
|
const adminUserId = getAdminUserId(ctx);
|
|
2257
2575
|
if (!adminUserId) {
|
|
2258
2576
|
ctx.status = 401;
|
|
@@ -2265,12 +2583,58 @@ const taskController = ({ strapi }) => ({
|
|
|
2265
2583
|
});
|
|
2266
2584
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2267
2585
|
ctx.status = 404;
|
|
2268
|
-
ctx.body = { error: "
|
|
2586
|
+
ctx.body = { error: "Note not found" };
|
|
2587
|
+
return;
|
|
2588
|
+
}
|
|
2589
|
+
const { title, content, category, tags, source } = ctx.request.body;
|
|
2590
|
+
const data = {};
|
|
2591
|
+
if (title !== void 0) data.title = title;
|
|
2592
|
+
if (content !== void 0) data.content = content;
|
|
2593
|
+
if (category !== void 0) data.category = category;
|
|
2594
|
+
if (tags !== void 0) data.tags = tags;
|
|
2595
|
+
if (source !== void 0) data.source = source;
|
|
2596
|
+
const note2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2597
|
+
documentId: id,
|
|
2598
|
+
data
|
|
2599
|
+
});
|
|
2600
|
+
ctx.body = { data: note2 };
|
|
2601
|
+
},
|
|
2602
|
+
async delete(ctx) {
|
|
2603
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2604
|
+
if (!adminUserId) {
|
|
2605
|
+
ctx.status = 401;
|
|
2606
|
+
ctx.body = { error: "Unauthorized" };
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
const { id } = ctx.params;
|
|
2610
|
+
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2611
|
+
documentId: id
|
|
2612
|
+
});
|
|
2613
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2614
|
+
ctx.status = 404;
|
|
2615
|
+
ctx.body = { error: "Note not found" };
|
|
2269
2616
|
return;
|
|
2270
2617
|
}
|
|
2271
2618
|
await strapi.documents(CONTENT_TYPE).delete({ documentId: id });
|
|
2272
2619
|
ctx.status = 200;
|
|
2273
2620
|
ctx.body = { data: { documentId: id } };
|
|
2621
|
+
},
|
|
2622
|
+
async clearAll(ctx) {
|
|
2623
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2624
|
+
if (!adminUserId) {
|
|
2625
|
+
ctx.status = 401;
|
|
2626
|
+
ctx.body = { error: "Unauthorized" };
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
const notes = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2630
|
+
filters: { adminUserId },
|
|
2631
|
+
fields: ["documentId"]
|
|
2632
|
+
});
|
|
2633
|
+
for (const note2 of notes) {
|
|
2634
|
+
await strapi.documents(CONTENT_TYPE).delete({ documentId: note2.documentId });
|
|
2635
|
+
}
|
|
2636
|
+
ctx.status = 200;
|
|
2637
|
+
ctx.body = { data: { deleted: notes.length } };
|
|
2274
2638
|
}
|
|
2275
2639
|
});
|
|
2276
2640
|
const controllers = {
|
|
@@ -2279,7 +2643,8 @@ const controllers = {
|
|
|
2279
2643
|
conversation: conversationController,
|
|
2280
2644
|
memory: memoryController,
|
|
2281
2645
|
"public-memory": publicMemoryController,
|
|
2282
|
-
task: taskController
|
|
2646
|
+
task: taskController,
|
|
2647
|
+
note: noteController
|
|
2283
2648
|
};
|
|
2284
2649
|
const promptInjection = [
|
|
2285
2650
|
"ignore (all |any )?(previous|prior|above) (instructions|prompts|rules)",
|
|
@@ -2649,6 +3014,36 @@ const adminAPIRoutes = {
|
|
|
2649
3014
|
path: "/tasks/:id",
|
|
2650
3015
|
handler: "task.delete",
|
|
2651
3016
|
config: { policies: [] }
|
|
3017
|
+
},
|
|
3018
|
+
{
|
|
3019
|
+
method: "GET",
|
|
3020
|
+
path: "/notes",
|
|
3021
|
+
handler: "note.find",
|
|
3022
|
+
config: { policies: [] }
|
|
3023
|
+
},
|
|
3024
|
+
{
|
|
3025
|
+
method: "POST",
|
|
3026
|
+
path: "/notes",
|
|
3027
|
+
handler: "note.create",
|
|
3028
|
+
config: { policies: [] }
|
|
3029
|
+
},
|
|
3030
|
+
{
|
|
3031
|
+
method: "PUT",
|
|
3032
|
+
path: "/notes/:id",
|
|
3033
|
+
handler: "note.update",
|
|
3034
|
+
config: { policies: [] }
|
|
3035
|
+
},
|
|
3036
|
+
{
|
|
3037
|
+
method: "DELETE",
|
|
3038
|
+
path: "/notes/clear",
|
|
3039
|
+
handler: "note.clearAll",
|
|
3040
|
+
config: { policies: [] }
|
|
3041
|
+
},
|
|
3042
|
+
{
|
|
3043
|
+
method: "DELETE",
|
|
3044
|
+
path: "/notes/:id",
|
|
3045
|
+
handler: "note.delete",
|
|
3046
|
+
config: { policies: [] }
|
|
2652
3047
|
}
|
|
2653
3048
|
]
|
|
2654
3049
|
};
|
|
@@ -2736,6 +3131,26 @@ function describeTools(tools) {
|
|
|
2736
3131
|
return `Available tools:
|
|
2737
3132
|
${lines.join("\n")}`;
|
|
2738
3133
|
}
|
|
3134
|
+
function trimMessages(messages, max) {
|
|
3135
|
+
if (messages.length <= max) return messages;
|
|
3136
|
+
const sliced = messages.slice(-max);
|
|
3137
|
+
while (sliced.length > 0 && hasOrphanedToolCalls(sliced[0])) {
|
|
3138
|
+
sliced.shift();
|
|
3139
|
+
}
|
|
3140
|
+
return sliced;
|
|
3141
|
+
}
|
|
3142
|
+
function hasOrphanedToolCalls(message) {
|
|
3143
|
+
if (message.role !== "assistant") return false;
|
|
3144
|
+
if (message.parts) {
|
|
3145
|
+
return message.parts.some(
|
|
3146
|
+
(part) => part.type === "tool-invocation"
|
|
3147
|
+
);
|
|
3148
|
+
}
|
|
3149
|
+
if (message.toolInvocations?.length) {
|
|
3150
|
+
return true;
|
|
3151
|
+
}
|
|
3152
|
+
return false;
|
|
3153
|
+
}
|
|
2739
3154
|
const DEFAULT_PREAMBLE = `You are a Strapi CMS assistant. Use your tools to fulfill user requests. When asked to create or update content, use the appropriate tool — do not tell the user you cannot. When performing bulk operations (e.g. publish multiple items), call multiple tools in parallel in a single step rather than one at a time.
|
|
2740
3155
|
|
|
2741
3156
|
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.
|
|
@@ -2799,7 +3214,7 @@ const service = ({ strapi }) => {
|
|
|
2799
3214
|
const maxMessages = config2?.maxConversationMessages ?? DEFAULT_MAX_CONVERSATION_MESSAGES;
|
|
2800
3215
|
const maxOutputTokens = config2?.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
|
|
2801
3216
|
const maxSteps = config2?.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
2802
|
-
const trimmedMessages = messages
|
|
3217
|
+
const trimmedMessages = trimMessages(messages, maxMessages);
|
|
2803
3218
|
const modelMessages = await ai.convertToModelMessages(trimmedMessages);
|
|
2804
3219
|
const tools = createTools(strapi, { adminUserId: options2?.adminUserId, enabledToolSources: options2?.enabledToolSources });
|
|
2805
3220
|
const toolsDescription = describeTools(tools);
|
|
@@ -2844,7 +3259,7 @@ ${lines.join("\n")}`;
|
|
|
2844
3259
|
const publicModel = publicConfig?.chatModel ?? DEFAULT_PUBLIC_CHAT_MODEL;
|
|
2845
3260
|
const allowedContentTypes = publicConfig?.allowedContentTypes ?? [];
|
|
2846
3261
|
const publicToolSources = publicConfig?.publicToolSources;
|
|
2847
|
-
const trimmedMessages = messages
|
|
3262
|
+
const trimmedMessages = trimMessages(messages, maxMessages);
|
|
2848
3263
|
const modelMessages = await ai.convertToModelMessages(trimmedMessages);
|
|
2849
3264
|
const tools = createPublicTools(strapi, allowedContentTypes, publicToolSources);
|
|
2850
3265
|
const toolsDescription = describeTools(tools);
|