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.mjs
CHANGED
|
@@ -10,6 +10,90 @@ import * as fs from "node:fs";
|
|
|
10
10
|
import * as path from "node:path";
|
|
11
11
|
import { randomUUID } from "node:crypto";
|
|
12
12
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
13
|
+
function toSnakeCase$1(str) {
|
|
14
|
+
return str.replace(/:/g, "__").replace(/-/g, "_").replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
15
|
+
}
|
|
16
|
+
function extractType(field) {
|
|
17
|
+
const def = field?._zod?.def;
|
|
18
|
+
if (!def) return "unknown";
|
|
19
|
+
switch (def.type) {
|
|
20
|
+
case "string":
|
|
21
|
+
return "string";
|
|
22
|
+
case "number":
|
|
23
|
+
return "number";
|
|
24
|
+
case "boolean":
|
|
25
|
+
return "boolean";
|
|
26
|
+
case "enum":
|
|
27
|
+
return Object.keys(def.entries).join(" | ");
|
|
28
|
+
case "optional":
|
|
29
|
+
return extractType({ _zod: { def: def.innerType } });
|
|
30
|
+
case "default":
|
|
31
|
+
return extractType({ _zod: { def: def.innerType } });
|
|
32
|
+
case "record":
|
|
33
|
+
return "object";
|
|
34
|
+
case "array":
|
|
35
|
+
return "array";
|
|
36
|
+
case "union":
|
|
37
|
+
return "string | array | object";
|
|
38
|
+
default:
|
|
39
|
+
return def.type || "unknown";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function formatParams(schema2) {
|
|
43
|
+
const shape = schema2.shape;
|
|
44
|
+
if (!shape || Object.keys(shape).length === 0) {
|
|
45
|
+
return "_No parameters._\n";
|
|
46
|
+
}
|
|
47
|
+
const rows = [];
|
|
48
|
+
rows.push("| Parameter | Type | Required | Description |");
|
|
49
|
+
rows.push("|-----------|------|----------|-------------|");
|
|
50
|
+
for (const [name, field] of Object.entries(shape)) {
|
|
51
|
+
const required = !field.isOptional?.();
|
|
52
|
+
const type = extractType(field);
|
|
53
|
+
const desc = (field.description || "").replace(/\|/g, "\\|");
|
|
54
|
+
rows.push(`| ${name} | ${type} | ${required ? "Yes" : "No"} | ${desc} |`);
|
|
55
|
+
}
|
|
56
|
+
return rows.join("\n") + "\n";
|
|
57
|
+
}
|
|
58
|
+
function generateToolGuide(registry) {
|
|
59
|
+
const tools = registry.getPublic();
|
|
60
|
+
const sources = registry.getToolSources();
|
|
61
|
+
const sections = [];
|
|
62
|
+
sections.push("# Strapi AI Tools Guide\n");
|
|
63
|
+
sections.push("## Getting Started\n");
|
|
64
|
+
sections.push(
|
|
65
|
+
"Start with `list_content_types` to discover your content types and their fields, then use `search_content` to query them.\n"
|
|
66
|
+
);
|
|
67
|
+
for (const source of sources) {
|
|
68
|
+
const heading = source.id === "built-in" ? "Built-in Tools" : source.label;
|
|
69
|
+
sections.push(`## ${heading}
|
|
70
|
+
`);
|
|
71
|
+
for (const toolName of source.tools) {
|
|
72
|
+
const def = tools.get(toolName);
|
|
73
|
+
if (!def) continue;
|
|
74
|
+
const mcpName = toSnakeCase$1(toolName);
|
|
75
|
+
sections.push(`### ${mcpName}
|
|
76
|
+
`);
|
|
77
|
+
sections.push(`${def.description}
|
|
78
|
+
`);
|
|
79
|
+
sections.push(formatParams(def.schema));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
sections.push("## Common Workflows\n");
|
|
83
|
+
sections.push("### Create a blog post\n");
|
|
84
|
+
sections.push(
|
|
85
|
+
"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"
|
|
86
|
+
);
|
|
87
|
+
sections.push("### Find and update content\n");
|
|
88
|
+
sections.push(
|
|
89
|
+
"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"
|
|
90
|
+
);
|
|
91
|
+
sections.push("### Content analytics\n");
|
|
92
|
+
sections.push(
|
|
93
|
+
"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"
|
|
94
|
+
);
|
|
95
|
+
return sections.join("\n");
|
|
96
|
+
}
|
|
13
97
|
function toSnakeCase(str) {
|
|
14
98
|
return str.replace(/:/g, "__").replace(/-/g, "_").replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
15
99
|
}
|
|
@@ -26,7 +110,8 @@ function createMcpServer(strapi) {
|
|
|
26
110
|
},
|
|
27
111
|
{
|
|
28
112
|
capabilities: {
|
|
29
|
-
tools: {}
|
|
113
|
+
tools: {},
|
|
114
|
+
resources: {}
|
|
30
115
|
}
|
|
31
116
|
}
|
|
32
117
|
);
|
|
@@ -54,6 +139,24 @@ function createMcpServer(strapi) {
|
|
|
54
139
|
}
|
|
55
140
|
);
|
|
56
141
|
}
|
|
142
|
+
const guideMarkdown = generateToolGuide(registry);
|
|
143
|
+
server.registerResource(
|
|
144
|
+
"Tool Guide",
|
|
145
|
+
"strapi://tools/guide",
|
|
146
|
+
{
|
|
147
|
+
description: "Complete guide to all available Strapi AI tools with parameters and usage examples",
|
|
148
|
+
mimeType: "text/markdown"
|
|
149
|
+
},
|
|
150
|
+
async () => ({
|
|
151
|
+
contents: [
|
|
152
|
+
{
|
|
153
|
+
uri: "strapi://tools/guide",
|
|
154
|
+
mimeType: "text/markdown",
|
|
155
|
+
text: guideMarkdown
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
})
|
|
159
|
+
);
|
|
57
160
|
strapi.log.info("[ai-sdk:mcp] MCP server created with tools:", { tools: toolNames });
|
|
58
161
|
return server;
|
|
59
162
|
}
|
|
@@ -219,7 +322,7 @@ class ToolRegistry {
|
|
|
219
322
|
}
|
|
220
323
|
}
|
|
221
324
|
const listContentTypesSchema = z.object({});
|
|
222
|
-
const listContentTypesDescription =
|
|
325
|
+
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.';
|
|
223
326
|
const INTERNAL_FIELDS = /* @__PURE__ */ new Set([
|
|
224
327
|
"createdAt",
|
|
225
328
|
"updatedAt",
|
|
@@ -373,7 +476,7 @@ const createContentSchema = z.object({
|
|
|
373
476
|
status: z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
374
477
|
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
375
478
|
});
|
|
376
|
-
const createContentDescription = "Create a new document in any Strapi content type (
|
|
479
|
+
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.";
|
|
377
480
|
async function createContent(strapi, params) {
|
|
378
481
|
const { contentType, data, status, locale } = params;
|
|
379
482
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -395,7 +498,7 @@ const updateContentSchema = z.object({
|
|
|
395
498
|
status: z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
396
499
|
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
397
500
|
});
|
|
398
|
-
const updateContentDescription = "Update an existing document in any Strapi content type.
|
|
501
|
+
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.";
|
|
399
502
|
async function updateContent(strapi, params) {
|
|
400
503
|
const { contentType, documentId, data, status, locale } = params;
|
|
401
504
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -468,7 +571,7 @@ async function sendEmail(strapi, params) {
|
|
|
468
571
|
subject: params.subject
|
|
469
572
|
};
|
|
470
573
|
}
|
|
471
|
-
const CONTENT_TYPE$
|
|
574
|
+
const CONTENT_TYPE$a = "plugin::ai-sdk.memory";
|
|
472
575
|
const saveMemorySchema = z.object({
|
|
473
576
|
content: z.string().describe('A short, factual statement to remember about the user (e.g. "User prefers dark mode", "Company name is Acme Corp")'),
|
|
474
577
|
category: z.string().optional().describe('Category for the memory (e.g. "preference", "project", "personal", "general"). Defaults to "general".')
|
|
@@ -479,7 +582,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
479
582
|
return { success: false, message: "Cannot save memory: user context not available." };
|
|
480
583
|
}
|
|
481
584
|
try {
|
|
482
|
-
await strapi.documents(CONTENT_TYPE$
|
|
585
|
+
await strapi.documents(CONTENT_TYPE$a).create({
|
|
483
586
|
data: {
|
|
484
587
|
content: params.content,
|
|
485
588
|
category: params.category || "general",
|
|
@@ -492,7 +595,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
492
595
|
return { success: false, message: `Failed to save memory: ${detail}` };
|
|
493
596
|
}
|
|
494
597
|
}
|
|
495
|
-
const CONTENT_TYPE$
|
|
598
|
+
const CONTENT_TYPE$9 = "plugin::ai-sdk.memory";
|
|
496
599
|
const recallMemoriesSchema = z.object({
|
|
497
600
|
query: z.string().optional().describe("Optional search term to filter memories by content"),
|
|
498
601
|
category: z.string().optional().describe('Optional category to filter by (e.g. "preference", "project", "personal")')
|
|
@@ -510,7 +613,7 @@ async function recallMemories(strapi, params, context) {
|
|
|
510
613
|
if (params.query) {
|
|
511
614
|
filters.content = { $containsi: params.query };
|
|
512
615
|
}
|
|
513
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
616
|
+
const memories = await strapi.documents(CONTENT_TYPE$9).findMany({
|
|
514
617
|
filters,
|
|
515
618
|
fields: ["content", "category"],
|
|
516
619
|
sort: { createdAt: "desc" }
|
|
@@ -536,7 +639,7 @@ const findOneContentSchema = z.object({
|
|
|
536
639
|
status: z.enum(["draft", "published"]).optional().describe("Document status filter."),
|
|
537
640
|
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
538
641
|
});
|
|
539
|
-
const findOneContentDescription = "Fetch a single document by its documentId
|
|
642
|
+
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.";
|
|
540
643
|
async function findOneContent(strapi, params) {
|
|
541
644
|
const { contentType, documentId, populate = "*", fields, status, locale } = params;
|
|
542
645
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -562,7 +665,7 @@ const uploadMediaSchema = z.object({
|
|
|
562
665
|
caption: z.string().optional().describe("Caption for the media file"),
|
|
563
666
|
alternativeText: z.string().optional().describe("Alternative text for accessibility")
|
|
564
667
|
});
|
|
565
|
-
const uploadMediaDescription = "Upload a media file from a URL to the Strapi media library.
|
|
668
|
+
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.";
|
|
566
669
|
async function uploadMedia(strapi, params) {
|
|
567
670
|
const { url, name, caption, alternativeText } = params;
|
|
568
671
|
let parsedUrl;
|
|
@@ -633,7 +736,7 @@ async function uploadMedia(strapi, params) {
|
|
|
633
736
|
usage: `To link this file to a content type field, use createContent or updateContent with: { "fieldName": ${uploadedFile.id} }`
|
|
634
737
|
};
|
|
635
738
|
}
|
|
636
|
-
const CONTENT_TYPE$
|
|
739
|
+
const CONTENT_TYPE$8 = "plugin::ai-sdk.public-memory";
|
|
637
740
|
const recallPublicMemoriesSchema = z.object({
|
|
638
741
|
query: z.string().optional().describe("Optional search term to filter public memories by content"),
|
|
639
742
|
category: z.string().optional().describe('Optional category to filter by (e.g. "faq", "product", "policy")')
|
|
@@ -644,7 +747,7 @@ async function recallPublicMemories(strapi, params) {
|
|
|
644
747
|
const filters = {};
|
|
645
748
|
if (params.category) filters.category = params.category;
|
|
646
749
|
if (params.query) filters.content = { $containsi: params.query };
|
|
647
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
750
|
+
const memories = await strapi.documents(CONTENT_TYPE$8).findMany({
|
|
648
751
|
filters,
|
|
649
752
|
fields: ["content", "category"],
|
|
650
753
|
sort: { createdAt: "desc" }
|
|
@@ -726,7 +829,7 @@ const aggregateContentSchema = z.object({
|
|
|
726
829
|
status: z.enum(["draft", "published"]).optional().describe("Filter by document status"),
|
|
727
830
|
locale: z.string().optional().describe("Locale code for i18n content")
|
|
728
831
|
});
|
|
729
|
-
const aggregateContentDescription = '
|
|
832
|
+
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.';
|
|
730
833
|
function buildBaseQuery(params) {
|
|
731
834
|
const { filters, status, locale, dateFrom, dateTo, dateField = "createdAt" } = params;
|
|
732
835
|
const query = {};
|
|
@@ -878,7 +981,7 @@ async function aggregateContent(strapi, params) {
|
|
|
878
981
|
throw new Error(`Unknown operation: ${operation}`);
|
|
879
982
|
}
|
|
880
983
|
}
|
|
881
|
-
const CONTENT_TYPE$
|
|
984
|
+
const CONTENT_TYPE$7 = "plugin::ai-sdk.task";
|
|
882
985
|
const manageTaskSchema = z.object({
|
|
883
986
|
action: z.enum(["create", "update", "complete", "list", "summary"]).describe(
|
|
884
987
|
"Action to perform: create a new task, update an existing task, complete (mark done), list open tasks, or get a summary."
|
|
@@ -894,14 +997,14 @@ const manageTaskSchema = z.object({
|
|
|
894
997
|
done: z.boolean().optional().describe("Set done status explicitly (for update action)."),
|
|
895
998
|
filters: z.record(z.string(), z.unknown()).optional().describe("Additional Strapi filters for list action.")
|
|
896
999
|
});
|
|
897
|
-
const manageTaskDescription = "Manage the user's task list.
|
|
1000
|
+
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.";
|
|
898
1001
|
async function resolveTask(strapi, adminUserId, documentId, title) {
|
|
899
1002
|
if (documentId) {
|
|
900
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1003
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).findOne({ documentId });
|
|
901
1004
|
if (task2 && task2.adminUserId === adminUserId) return task2;
|
|
902
1005
|
}
|
|
903
1006
|
if (title) {
|
|
904
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1007
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
905
1008
|
filters: {
|
|
906
1009
|
adminUserId,
|
|
907
1010
|
title: { $containsi: title }
|
|
@@ -954,7 +1057,7 @@ async function manageTask(strapi, params, context) {
|
|
|
954
1057
|
if (params.consequence !== void 0) data.consequence = params.consequence;
|
|
955
1058
|
if (params.impact !== void 0) data.impact = params.impact;
|
|
956
1059
|
if (params.dueDate !== void 0) data.dueDate = params.dueDate;
|
|
957
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1060
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
958
1061
|
documentId: duplicate.documentId,
|
|
959
1062
|
data
|
|
960
1063
|
});
|
|
@@ -965,7 +1068,7 @@ async function manageTask(strapi, params, context) {
|
|
|
965
1068
|
data: updated
|
|
966
1069
|
};
|
|
967
1070
|
}
|
|
968
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1071
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).create({
|
|
969
1072
|
data: {
|
|
970
1073
|
title: params.title,
|
|
971
1074
|
description: params.description,
|
|
@@ -994,7 +1097,7 @@ async function manageTask(strapi, params, context) {
|
|
|
994
1097
|
for (const key of ["title", "description", "content", "priority", "consequence", "impact", "dueDate", "done"]) {
|
|
995
1098
|
if (params[key] !== void 0) data[key] = params[key];
|
|
996
1099
|
}
|
|
997
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1100
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
998
1101
|
documentId: existing.documentId,
|
|
999
1102
|
data
|
|
1000
1103
|
});
|
|
@@ -1005,7 +1108,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1005
1108
|
if (!toComplete) {
|
|
1006
1109
|
return { success: false, message: "Task not found. Provide a documentId or a title to search by." };
|
|
1007
1110
|
}
|
|
1008
|
-
await strapi.documents(CONTENT_TYPE$
|
|
1111
|
+
await strapi.documents(CONTENT_TYPE$7).update({
|
|
1009
1112
|
documentId: toComplete.documentId,
|
|
1010
1113
|
data: { done: true }
|
|
1011
1114
|
});
|
|
@@ -1017,7 +1120,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1017
1120
|
done: false,
|
|
1018
1121
|
...params.filters
|
|
1019
1122
|
};
|
|
1020
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1123
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1021
1124
|
filters
|
|
1022
1125
|
});
|
|
1023
1126
|
const sorted = tasks.sort((a, b) => {
|
|
@@ -1046,7 +1149,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1046
1149
|
};
|
|
1047
1150
|
}
|
|
1048
1151
|
case "summary": {
|
|
1049
|
-
const allOpen = await strapi.documents(CONTENT_TYPE$
|
|
1152
|
+
const allOpen = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1050
1153
|
filters: { adminUserId, done: false }
|
|
1051
1154
|
});
|
|
1052
1155
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -1083,6 +1186,82 @@ async function manageTask(strapi, params, context) {
|
|
|
1083
1186
|
return { success: false, message: `Task operation failed: ${detail}` };
|
|
1084
1187
|
}
|
|
1085
1188
|
}
|
|
1189
|
+
const CONTENT_TYPE$6 = "plugin::ai-sdk.note";
|
|
1190
|
+
const saveNoteSchema = z.object({
|
|
1191
|
+
title: z.string().optional().describe("A short title or label for the note"),
|
|
1192
|
+
content: z.string().describe("The note content in markdown format. Can include code blocks, lists, links, etc."),
|
|
1193
|
+
category: z.string().optional().describe('Category for the note: "research", "snippet", "idea", or "reference". Defaults to "research".'),
|
|
1194
|
+
tags: z.string().optional().describe('Comma-separated tags for filtering (e.g. "strapi, api, tutorial")'),
|
|
1195
|
+
source: z.string().optional().describe('Where this note came from (e.g. "conversation", "web research", a URL)')
|
|
1196
|
+
});
|
|
1197
|
+
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.";
|
|
1198
|
+
async function saveNote(strapi, params, context) {
|
|
1199
|
+
if (!context?.adminUserId) {
|
|
1200
|
+
return { success: false, message: "Cannot save note: user context not available." };
|
|
1201
|
+
}
|
|
1202
|
+
try {
|
|
1203
|
+
await strapi.documents(CONTENT_TYPE$6).create({
|
|
1204
|
+
data: {
|
|
1205
|
+
title: params.title || "",
|
|
1206
|
+
content: params.content,
|
|
1207
|
+
category: params.category || "research",
|
|
1208
|
+
tags: params.tags || "",
|
|
1209
|
+
source: params.source || "conversation",
|
|
1210
|
+
adminUserId: context.adminUserId
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
const label = params.title ? `"${params.title}"` : "Note";
|
|
1214
|
+
return { success: true, message: `${label} saved to research notes.` };
|
|
1215
|
+
} catch (error) {
|
|
1216
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1217
|
+
return { success: false, message: `Failed to save note: ${detail}` };
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
const CONTENT_TYPE$5 = "plugin::ai-sdk.note";
|
|
1221
|
+
const recallNotesSchema = z.object({
|
|
1222
|
+
query: z.string().optional().describe("Optional search term to filter notes by title or content"),
|
|
1223
|
+
category: z.string().optional().describe('Optional category to filter by: "research", "snippet", "idea", "reference"'),
|
|
1224
|
+
tag: z.string().optional().describe("Optional tag to filter by (matches within comma-separated tags)")
|
|
1225
|
+
});
|
|
1226
|
+
const recallNotesDescription = "Recall saved research notes, snippets, ideas, and references. Use this to look up previously saved notes. Without parameters, returns all notes.";
|
|
1227
|
+
async function recallNotes(strapi, params, context) {
|
|
1228
|
+
if (!context?.adminUserId) {
|
|
1229
|
+
return { success: false, notes: [], count: 0 };
|
|
1230
|
+
}
|
|
1231
|
+
try {
|
|
1232
|
+
const filters = { adminUserId: context.adminUserId };
|
|
1233
|
+
if (params.category) {
|
|
1234
|
+
filters.category = params.category;
|
|
1235
|
+
}
|
|
1236
|
+
if (params.query) {
|
|
1237
|
+
filters.$or = [
|
|
1238
|
+
{ title: { $containsi: params.query } },
|
|
1239
|
+
{ content: { $containsi: params.query } }
|
|
1240
|
+
];
|
|
1241
|
+
}
|
|
1242
|
+
if (params.tag) {
|
|
1243
|
+
filters.tags = { $containsi: params.tag };
|
|
1244
|
+
}
|
|
1245
|
+
const notes = await strapi.documents(CONTENT_TYPE$5).findMany({
|
|
1246
|
+
filters,
|
|
1247
|
+
fields: ["title", "content", "category", "tags", "source"],
|
|
1248
|
+
sort: { createdAt: "desc" }
|
|
1249
|
+
});
|
|
1250
|
+
return {
|
|
1251
|
+
success: true,
|
|
1252
|
+
notes: notes.map((n) => ({
|
|
1253
|
+
title: n.title || "",
|
|
1254
|
+
content: n.content,
|
|
1255
|
+
category: n.category,
|
|
1256
|
+
tags: n.tags || "",
|
|
1257
|
+
source: n.source || ""
|
|
1258
|
+
})),
|
|
1259
|
+
count: notes.length
|
|
1260
|
+
};
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
return { success: false, notes: [], count: 0 };
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1086
1265
|
const listContentTypesTool = {
|
|
1087
1266
|
name: "listContentTypes",
|
|
1088
1267
|
description: listContentTypesDescription,
|
|
@@ -1213,6 +1392,20 @@ const manageTaskTool = {
|
|
|
1213
1392
|
execute: async (args, strapi, context) => manageTask(strapi, args, context),
|
|
1214
1393
|
internal: true
|
|
1215
1394
|
};
|
|
1395
|
+
const saveNoteTool = {
|
|
1396
|
+
name: "saveNote",
|
|
1397
|
+
description: saveNoteDescription,
|
|
1398
|
+
schema: saveNoteSchema,
|
|
1399
|
+
execute: async (args, strapi, context) => saveNote(strapi, args, context),
|
|
1400
|
+
internal: true
|
|
1401
|
+
};
|
|
1402
|
+
const recallNotesTool = {
|
|
1403
|
+
name: "recallNotes",
|
|
1404
|
+
description: recallNotesDescription,
|
|
1405
|
+
schema: recallNotesSchema,
|
|
1406
|
+
execute: async (args, strapi, context) => recallNotes(strapi, args, context),
|
|
1407
|
+
internal: true
|
|
1408
|
+
};
|
|
1216
1409
|
const builtInTools = [
|
|
1217
1410
|
listContentTypesTool,
|
|
1218
1411
|
searchContentTool,
|
|
@@ -1225,7 +1418,9 @@ const builtInTools = [
|
|
|
1225
1418
|
recallMemoriesTool,
|
|
1226
1419
|
recallPublicMemoriesTool,
|
|
1227
1420
|
aggregateContentTool,
|
|
1228
|
-
manageTaskTool
|
|
1421
|
+
manageTaskTool,
|
|
1422
|
+
saveNoteTool,
|
|
1423
|
+
recallNotesTool
|
|
1229
1424
|
];
|
|
1230
1425
|
const PLUGIN_ID$2 = "ai-sdk";
|
|
1231
1426
|
const bootstrap = ({ strapi }) => {
|
|
@@ -1396,17 +1591,17 @@ const config = {
|
|
|
1396
1591
|
}
|
|
1397
1592
|
}
|
|
1398
1593
|
};
|
|
1399
|
-
const kind$
|
|
1400
|
-
const collectionName$
|
|
1401
|
-
const info$
|
|
1594
|
+
const kind$4 = "collectionType";
|
|
1595
|
+
const collectionName$4 = "ai_sdk_conversations";
|
|
1596
|
+
const info$4 = {
|
|
1402
1597
|
singularName: "conversation",
|
|
1403
1598
|
pluralName: "conversations",
|
|
1404
1599
|
displayName: "AI Conversation"
|
|
1405
1600
|
};
|
|
1406
|
-
const options$
|
|
1601
|
+
const options$4 = {
|
|
1407
1602
|
draftAndPublish: false
|
|
1408
1603
|
};
|
|
1409
|
-
const pluginOptions$
|
|
1604
|
+
const pluginOptions$4 = {
|
|
1410
1605
|
"content-manager": {
|
|
1411
1606
|
visible: false
|
|
1412
1607
|
},
|
|
@@ -1414,7 +1609,7 @@ const pluginOptions$3 = {
|
|
|
1414
1609
|
visible: false
|
|
1415
1610
|
}
|
|
1416
1611
|
};
|
|
1417
|
-
const attributes$
|
|
1612
|
+
const attributes$4 = {
|
|
1418
1613
|
title: {
|
|
1419
1614
|
type: "string",
|
|
1420
1615
|
required: true,
|
|
@@ -1429,26 +1624,26 @@ const attributes$3 = {
|
|
|
1429
1624
|
required: true
|
|
1430
1625
|
}
|
|
1431
1626
|
};
|
|
1432
|
-
const schema$
|
|
1433
|
-
kind: kind$
|
|
1434
|
-
collectionName: collectionName$
|
|
1435
|
-
info: info$
|
|
1436
|
-
options: options$
|
|
1437
|
-
pluginOptions: pluginOptions$
|
|
1438
|
-
attributes: attributes$
|
|
1627
|
+
const schema$4 = {
|
|
1628
|
+
kind: kind$4,
|
|
1629
|
+
collectionName: collectionName$4,
|
|
1630
|
+
info: info$4,
|
|
1631
|
+
options: options$4,
|
|
1632
|
+
pluginOptions: pluginOptions$4,
|
|
1633
|
+
attributes: attributes$4
|
|
1439
1634
|
};
|
|
1440
|
-
const conversation = { schema: schema$
|
|
1441
|
-
const kind$
|
|
1442
|
-
const collectionName$
|
|
1443
|
-
const info$
|
|
1635
|
+
const conversation = { schema: schema$4 };
|
|
1636
|
+
const kind$3 = "collectionType";
|
|
1637
|
+
const collectionName$3 = "ai_sdk_memories";
|
|
1638
|
+
const info$3 = {
|
|
1444
1639
|
singularName: "memory",
|
|
1445
1640
|
pluralName: "memories",
|
|
1446
1641
|
displayName: "AI Memory"
|
|
1447
1642
|
};
|
|
1448
|
-
const options$
|
|
1643
|
+
const options$3 = {
|
|
1449
1644
|
draftAndPublish: false
|
|
1450
1645
|
};
|
|
1451
|
-
const pluginOptions$
|
|
1646
|
+
const pluginOptions$3 = {
|
|
1452
1647
|
"content-manager": {
|
|
1453
1648
|
visible: false
|
|
1454
1649
|
},
|
|
@@ -1456,9 +1651,9 @@ const pluginOptions$2 = {
|
|
|
1456
1651
|
visible: false
|
|
1457
1652
|
}
|
|
1458
1653
|
};
|
|
1459
|
-
const attributes$
|
|
1654
|
+
const attributes$3 = {
|
|
1460
1655
|
content: {
|
|
1461
|
-
type: "
|
|
1656
|
+
type: "richtext",
|
|
1462
1657
|
required: true
|
|
1463
1658
|
},
|
|
1464
1659
|
category: {
|
|
@@ -1476,26 +1671,26 @@ const attributes$2 = {
|
|
|
1476
1671
|
required: true
|
|
1477
1672
|
}
|
|
1478
1673
|
};
|
|
1479
|
-
const schema$
|
|
1480
|
-
kind: kind$
|
|
1481
|
-
collectionName: collectionName$
|
|
1482
|
-
info: info$
|
|
1483
|
-
options: options$
|
|
1484
|
-
pluginOptions: pluginOptions$
|
|
1485
|
-
attributes: attributes$
|
|
1674
|
+
const schema$3 = {
|
|
1675
|
+
kind: kind$3,
|
|
1676
|
+
collectionName: collectionName$3,
|
|
1677
|
+
info: info$3,
|
|
1678
|
+
options: options$3,
|
|
1679
|
+
pluginOptions: pluginOptions$3,
|
|
1680
|
+
attributes: attributes$3
|
|
1486
1681
|
};
|
|
1487
|
-
const memory = { schema: schema$
|
|
1488
|
-
const kind$
|
|
1489
|
-
const collectionName$
|
|
1490
|
-
const info$
|
|
1682
|
+
const memory = { schema: schema$3 };
|
|
1683
|
+
const kind$2 = "collectionType";
|
|
1684
|
+
const collectionName$2 = "ai_sdk_public_memories";
|
|
1685
|
+
const info$2 = {
|
|
1491
1686
|
singularName: "public-memory",
|
|
1492
1687
|
pluralName: "public-memories",
|
|
1493
1688
|
displayName: "AI Public Memory"
|
|
1494
1689
|
};
|
|
1495
|
-
const options$
|
|
1690
|
+
const options$2 = {
|
|
1496
1691
|
draftAndPublish: false
|
|
1497
1692
|
};
|
|
1498
|
-
const pluginOptions$
|
|
1693
|
+
const pluginOptions$2 = {
|
|
1499
1694
|
"content-manager": {
|
|
1500
1695
|
visible: false
|
|
1501
1696
|
},
|
|
@@ -1503,7 +1698,7 @@ const pluginOptions$1 = {
|
|
|
1503
1698
|
visible: false
|
|
1504
1699
|
}
|
|
1505
1700
|
};
|
|
1506
|
-
const attributes$
|
|
1701
|
+
const attributes$2 = {
|
|
1507
1702
|
content: {
|
|
1508
1703
|
type: "text",
|
|
1509
1704
|
required: true
|
|
@@ -1519,26 +1714,26 @@ const attributes$1 = {
|
|
|
1519
1714
|
"default": "general"
|
|
1520
1715
|
}
|
|
1521
1716
|
};
|
|
1522
|
-
const schema$
|
|
1523
|
-
kind: kind$
|
|
1524
|
-
collectionName: collectionName$
|
|
1525
|
-
info: info$
|
|
1526
|
-
options: options$
|
|
1527
|
-
pluginOptions: pluginOptions$
|
|
1528
|
-
attributes: attributes$
|
|
1717
|
+
const schema$2 = {
|
|
1718
|
+
kind: kind$2,
|
|
1719
|
+
collectionName: collectionName$2,
|
|
1720
|
+
info: info$2,
|
|
1721
|
+
options: options$2,
|
|
1722
|
+
pluginOptions: pluginOptions$2,
|
|
1723
|
+
attributes: attributes$2
|
|
1529
1724
|
};
|
|
1530
|
-
const publicMemory = { schema: schema$
|
|
1531
|
-
const kind = "collectionType";
|
|
1532
|
-
const collectionName = "ai_sdk_tasks";
|
|
1533
|
-
const info = {
|
|
1725
|
+
const publicMemory = { schema: schema$2 };
|
|
1726
|
+
const kind$1 = "collectionType";
|
|
1727
|
+
const collectionName$1 = "ai_sdk_tasks";
|
|
1728
|
+
const info$1 = {
|
|
1534
1729
|
singularName: "task",
|
|
1535
1730
|
pluralName: "tasks",
|
|
1536
1731
|
displayName: "AI Task"
|
|
1537
1732
|
};
|
|
1538
|
-
const options = {
|
|
1733
|
+
const options$1 = {
|
|
1539
1734
|
draftAndPublish: false
|
|
1540
1735
|
};
|
|
1541
|
-
const pluginOptions = {
|
|
1736
|
+
const pluginOptions$1 = {
|
|
1542
1737
|
"content-manager": {
|
|
1543
1738
|
visible: true
|
|
1544
1739
|
},
|
|
@@ -1546,7 +1741,7 @@ const pluginOptions = {
|
|
|
1546
1741
|
visible: false
|
|
1547
1742
|
}
|
|
1548
1743
|
};
|
|
1549
|
-
const attributes = {
|
|
1744
|
+
const attributes$1 = {
|
|
1550
1745
|
title: {
|
|
1551
1746
|
type: "string",
|
|
1552
1747
|
required: true
|
|
@@ -1591,6 +1786,62 @@ const attributes = {
|
|
|
1591
1786
|
required: true
|
|
1592
1787
|
}
|
|
1593
1788
|
};
|
|
1789
|
+
const schema$1 = {
|
|
1790
|
+
kind: kind$1,
|
|
1791
|
+
collectionName: collectionName$1,
|
|
1792
|
+
info: info$1,
|
|
1793
|
+
options: options$1,
|
|
1794
|
+
pluginOptions: pluginOptions$1,
|
|
1795
|
+
attributes: attributes$1
|
|
1796
|
+
};
|
|
1797
|
+
const task = { schema: schema$1 };
|
|
1798
|
+
const kind = "collectionType";
|
|
1799
|
+
const collectionName = "ai_sdk_notes";
|
|
1800
|
+
const info = {
|
|
1801
|
+
singularName: "note",
|
|
1802
|
+
pluralName: "notes",
|
|
1803
|
+
displayName: "AI Note"
|
|
1804
|
+
};
|
|
1805
|
+
const options = {
|
|
1806
|
+
draftAndPublish: false
|
|
1807
|
+
};
|
|
1808
|
+
const pluginOptions = {
|
|
1809
|
+
"content-manager": {
|
|
1810
|
+
visible: false
|
|
1811
|
+
},
|
|
1812
|
+
"content-type-builder": {
|
|
1813
|
+
visible: false
|
|
1814
|
+
}
|
|
1815
|
+
};
|
|
1816
|
+
const attributes = {
|
|
1817
|
+
title: {
|
|
1818
|
+
type: "string"
|
|
1819
|
+
},
|
|
1820
|
+
content: {
|
|
1821
|
+
type: "richtext",
|
|
1822
|
+
required: true
|
|
1823
|
+
},
|
|
1824
|
+
category: {
|
|
1825
|
+
type: "enumeration",
|
|
1826
|
+
"enum": [
|
|
1827
|
+
"research",
|
|
1828
|
+
"snippet",
|
|
1829
|
+
"idea",
|
|
1830
|
+
"reference"
|
|
1831
|
+
],
|
|
1832
|
+
"default": "research"
|
|
1833
|
+
},
|
|
1834
|
+
tags: {
|
|
1835
|
+
type: "text"
|
|
1836
|
+
},
|
|
1837
|
+
source: {
|
|
1838
|
+
type: "string"
|
|
1839
|
+
},
|
|
1840
|
+
adminUserId: {
|
|
1841
|
+
type: "integer",
|
|
1842
|
+
required: true
|
|
1843
|
+
}
|
|
1844
|
+
};
|
|
1594
1845
|
const schema = {
|
|
1595
1846
|
kind,
|
|
1596
1847
|
collectionName,
|
|
@@ -1599,8 +1850,8 @@ const schema = {
|
|
|
1599
1850
|
pluginOptions,
|
|
1600
1851
|
attributes
|
|
1601
1852
|
};
|
|
1602
|
-
const
|
|
1603
|
-
const contentTypes = { conversation, memory, "public-memory": publicMemory, task };
|
|
1853
|
+
const note = { schema };
|
|
1854
|
+
const contentTypes = { conversation, memory, "public-memory": publicMemory, task, note };
|
|
1604
1855
|
function getService(strapi, ctx) {
|
|
1605
1856
|
const service2 = strapi.plugin("ai-sdk").service("service");
|
|
1606
1857
|
if (!service2.isInitialized()) {
|
|
@@ -1916,20 +2167,20 @@ const mcpController = ({ strapi }) => {
|
|
|
1916
2167
|
}
|
|
1917
2168
|
};
|
|
1918
2169
|
};
|
|
1919
|
-
const CONTENT_TYPE$
|
|
1920
|
-
function getAdminUserId$
|
|
2170
|
+
const CONTENT_TYPE$4 = "plugin::ai-sdk.conversation";
|
|
2171
|
+
function getAdminUserId$3(ctx) {
|
|
1921
2172
|
const id = ctx.state?.user?.id;
|
|
1922
2173
|
return typeof id === "number" ? id : null;
|
|
1923
2174
|
}
|
|
1924
2175
|
const conversationController = ({ strapi }) => ({
|
|
1925
2176
|
async find(ctx) {
|
|
1926
|
-
const adminUserId = getAdminUserId$
|
|
2177
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1927
2178
|
if (!adminUserId) {
|
|
1928
2179
|
ctx.status = 401;
|
|
1929
2180
|
ctx.body = { error: "Unauthorized" };
|
|
1930
2181
|
return;
|
|
1931
2182
|
}
|
|
1932
|
-
const conversations = await strapi.documents(CONTENT_TYPE$
|
|
2183
|
+
const conversations = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
1933
2184
|
filters: { adminUserId },
|
|
1934
2185
|
fields: ["title", "createdAt", "updatedAt"],
|
|
1935
2186
|
sort: { updatedAt: "desc" }
|
|
@@ -1937,14 +2188,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1937
2188
|
ctx.body = { data: conversations };
|
|
1938
2189
|
},
|
|
1939
2190
|
async findOne(ctx) {
|
|
1940
|
-
const adminUserId = getAdminUserId$
|
|
2191
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1941
2192
|
if (!adminUserId) {
|
|
1942
2193
|
ctx.status = 401;
|
|
1943
2194
|
ctx.body = { error: "Unauthorized" };
|
|
1944
2195
|
return;
|
|
1945
2196
|
}
|
|
1946
2197
|
const { id } = ctx.params;
|
|
1947
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2198
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1948
2199
|
documentId: id
|
|
1949
2200
|
});
|
|
1950
2201
|
if (!conversation2 || conversation2.adminUserId !== adminUserId) {
|
|
@@ -1955,14 +2206,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1955
2206
|
ctx.body = { data: conversation2 };
|
|
1956
2207
|
},
|
|
1957
2208
|
async create(ctx) {
|
|
1958
|
-
const adminUserId = getAdminUserId$
|
|
2209
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1959
2210
|
if (!adminUserId) {
|
|
1960
2211
|
ctx.status = 401;
|
|
1961
2212
|
ctx.body = { error: "Unauthorized" };
|
|
1962
2213
|
return;
|
|
1963
2214
|
}
|
|
1964
2215
|
const { title, messages } = ctx.request.body;
|
|
1965
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2216
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).create({
|
|
1966
2217
|
data: {
|
|
1967
2218
|
title: title || "New conversation",
|
|
1968
2219
|
messages: messages || [],
|
|
@@ -1973,14 +2224,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1973
2224
|
ctx.body = { data: conversation2 };
|
|
1974
2225
|
},
|
|
1975
2226
|
async update(ctx) {
|
|
1976
|
-
const adminUserId = getAdminUserId$
|
|
2227
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1977
2228
|
if (!adminUserId) {
|
|
1978
2229
|
ctx.status = 401;
|
|
1979
2230
|
ctx.body = { error: "Unauthorized" };
|
|
1980
2231
|
return;
|
|
1981
2232
|
}
|
|
1982
2233
|
const { id } = ctx.params;
|
|
1983
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2234
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1984
2235
|
documentId: id
|
|
1985
2236
|
});
|
|
1986
2237
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1992,21 +2243,21 @@ const conversationController = ({ strapi }) => ({
|
|
|
1992
2243
|
const data = {};
|
|
1993
2244
|
if (title !== void 0) data.title = title;
|
|
1994
2245
|
if (messages !== void 0) data.messages = messages;
|
|
1995
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2246
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).update({
|
|
1996
2247
|
documentId: id,
|
|
1997
2248
|
data
|
|
1998
2249
|
});
|
|
1999
2250
|
ctx.body = { data: conversation2 };
|
|
2000
2251
|
},
|
|
2001
2252
|
async delete(ctx) {
|
|
2002
|
-
const adminUserId = getAdminUserId$
|
|
2253
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
2003
2254
|
if (!adminUserId) {
|
|
2004
2255
|
ctx.status = 401;
|
|
2005
2256
|
ctx.body = { error: "Unauthorized" };
|
|
2006
2257
|
return;
|
|
2007
2258
|
}
|
|
2008
2259
|
const { id } = ctx.params;
|
|
2009
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2260
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
2010
2261
|
documentId: id
|
|
2011
2262
|
});
|
|
2012
2263
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2014,25 +2265,25 @@ const conversationController = ({ strapi }) => ({
|
|
|
2014
2265
|
ctx.body = { error: "Conversation not found" };
|
|
2015
2266
|
return;
|
|
2016
2267
|
}
|
|
2017
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2268
|
+
await strapi.documents(CONTENT_TYPE$4).delete({ documentId: id });
|
|
2018
2269
|
ctx.status = 200;
|
|
2019
2270
|
ctx.body = { data: { documentId: id } };
|
|
2020
2271
|
}
|
|
2021
2272
|
});
|
|
2022
|
-
const CONTENT_TYPE$
|
|
2023
|
-
function getAdminUserId$
|
|
2273
|
+
const CONTENT_TYPE$3 = "plugin::ai-sdk.memory";
|
|
2274
|
+
function getAdminUserId$2(ctx) {
|
|
2024
2275
|
const id = ctx.state?.user?.id;
|
|
2025
2276
|
return typeof id === "number" ? id : null;
|
|
2026
2277
|
}
|
|
2027
2278
|
const memoryController = ({ strapi }) => ({
|
|
2028
2279
|
async find(ctx) {
|
|
2029
|
-
const adminUserId = getAdminUserId$
|
|
2280
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2030
2281
|
if (!adminUserId) {
|
|
2031
2282
|
ctx.status = 401;
|
|
2032
2283
|
ctx.body = { error: "Unauthorized" };
|
|
2033
2284
|
return;
|
|
2034
2285
|
}
|
|
2035
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2286
|
+
const memories = await strapi.documents(CONTENT_TYPE$3).findMany({
|
|
2036
2287
|
filters: { adminUserId },
|
|
2037
2288
|
fields: ["content", "category", "createdAt"],
|
|
2038
2289
|
sort: { createdAt: "desc" }
|
|
@@ -2040,7 +2291,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2040
2291
|
ctx.body = { data: memories };
|
|
2041
2292
|
},
|
|
2042
2293
|
async create(ctx) {
|
|
2043
|
-
const adminUserId = getAdminUserId$
|
|
2294
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2044
2295
|
if (!adminUserId) {
|
|
2045
2296
|
ctx.status = 401;
|
|
2046
2297
|
ctx.body = { error: "Unauthorized" };
|
|
@@ -2052,7 +2303,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2052
2303
|
ctx.body = { error: "content is required" };
|
|
2053
2304
|
return;
|
|
2054
2305
|
}
|
|
2055
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2306
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).create({
|
|
2056
2307
|
data: {
|
|
2057
2308
|
content,
|
|
2058
2309
|
category: category || "general",
|
|
@@ -2063,14 +2314,14 @@ const memoryController = ({ strapi }) => ({
|
|
|
2063
2314
|
ctx.body = { data: memory2 };
|
|
2064
2315
|
},
|
|
2065
2316
|
async update(ctx) {
|
|
2066
|
-
const adminUserId = getAdminUserId$
|
|
2317
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2067
2318
|
if (!adminUserId) {
|
|
2068
2319
|
ctx.status = 401;
|
|
2069
2320
|
ctx.body = { error: "Unauthorized" };
|
|
2070
2321
|
return;
|
|
2071
2322
|
}
|
|
2072
2323
|
const { id } = ctx.params;
|
|
2073
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2324
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2074
2325
|
documentId: id
|
|
2075
2326
|
});
|
|
2076
2327
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2082,21 +2333,21 @@ const memoryController = ({ strapi }) => ({
|
|
|
2082
2333
|
const data = {};
|
|
2083
2334
|
if (content !== void 0) data.content = content;
|
|
2084
2335
|
if (category !== void 0) data.category = category;
|
|
2085
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2336
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).update({
|
|
2086
2337
|
documentId: id,
|
|
2087
2338
|
data
|
|
2088
2339
|
});
|
|
2089
2340
|
ctx.body = { data: memory2 };
|
|
2090
2341
|
},
|
|
2091
2342
|
async delete(ctx) {
|
|
2092
|
-
const adminUserId = getAdminUserId$
|
|
2343
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2093
2344
|
if (!adminUserId) {
|
|
2094
2345
|
ctx.status = 401;
|
|
2095
2346
|
ctx.body = { error: "Unauthorized" };
|
|
2096
2347
|
return;
|
|
2097
2348
|
}
|
|
2098
2349
|
const { id } = ctx.params;
|
|
2099
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2350
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2100
2351
|
documentId: id
|
|
2101
2352
|
});
|
|
2102
2353
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2104,15 +2355,15 @@ const memoryController = ({ strapi }) => ({
|
|
|
2104
2355
|
ctx.body = { error: "Memory not found" };
|
|
2105
2356
|
return;
|
|
2106
2357
|
}
|
|
2107
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2358
|
+
await strapi.documents(CONTENT_TYPE$3).delete({ documentId: id });
|
|
2108
2359
|
ctx.status = 200;
|
|
2109
2360
|
ctx.body = { data: { documentId: id } };
|
|
2110
2361
|
}
|
|
2111
2362
|
});
|
|
2112
|
-
const CONTENT_TYPE$
|
|
2363
|
+
const CONTENT_TYPE$2 = "plugin::ai-sdk.public-memory";
|
|
2113
2364
|
const publicMemoryController = ({ strapi }) => ({
|
|
2114
2365
|
async find(ctx) {
|
|
2115
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2366
|
+
const memories = await strapi.documents(CONTENT_TYPE$2).findMany({
|
|
2116
2367
|
fields: ["content", "category", "createdAt"],
|
|
2117
2368
|
sort: { createdAt: "desc" }
|
|
2118
2369
|
});
|
|
@@ -2125,7 +2376,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2125
2376
|
ctx.body = { error: "content is required" };
|
|
2126
2377
|
return;
|
|
2127
2378
|
}
|
|
2128
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2379
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).create({
|
|
2129
2380
|
data: { content, category: category || "general" }
|
|
2130
2381
|
});
|
|
2131
2382
|
ctx.status = 201;
|
|
@@ -2133,7 +2384,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2133
2384
|
},
|
|
2134
2385
|
async update(ctx) {
|
|
2135
2386
|
const { id } = ctx.params;
|
|
2136
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2387
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2137
2388
|
if (!existing) {
|
|
2138
2389
|
ctx.status = 404;
|
|
2139
2390
|
ctx.body = { error: "Public memory not found" };
|
|
@@ -2143,7 +2394,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2143
2394
|
const data = {};
|
|
2144
2395
|
if (content !== void 0) data.content = content;
|
|
2145
2396
|
if (category !== void 0) data.category = category;
|
|
2146
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2397
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).update({
|
|
2147
2398
|
documentId: id,
|
|
2148
2399
|
data
|
|
2149
2400
|
});
|
|
@@ -2151,45 +2402,45 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2151
2402
|
},
|
|
2152
2403
|
async delete(ctx) {
|
|
2153
2404
|
const { id } = ctx.params;
|
|
2154
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2405
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2155
2406
|
if (!existing) {
|
|
2156
2407
|
ctx.status = 404;
|
|
2157
2408
|
ctx.body = { error: "Public memory not found" };
|
|
2158
2409
|
return;
|
|
2159
2410
|
}
|
|
2160
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2411
|
+
await strapi.documents(CONTENT_TYPE$2).delete({ documentId: id });
|
|
2161
2412
|
ctx.status = 200;
|
|
2162
2413
|
ctx.body = { data: { documentId: id } };
|
|
2163
2414
|
}
|
|
2164
2415
|
});
|
|
2165
|
-
const CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
2166
|
-
function getAdminUserId(ctx) {
|
|
2416
|
+
const CONTENT_TYPE$1 = "plugin::ai-sdk.task";
|
|
2417
|
+
function getAdminUserId$1(ctx) {
|
|
2167
2418
|
const id = ctx.state?.user?.id;
|
|
2168
2419
|
return typeof id === "number" ? id : null;
|
|
2169
2420
|
}
|
|
2170
2421
|
const taskController = ({ strapi }) => ({
|
|
2171
2422
|
async find(ctx) {
|
|
2172
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2423
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2173
2424
|
if (!adminUserId) {
|
|
2174
2425
|
ctx.status = 401;
|
|
2175
2426
|
ctx.body = { error: "Unauthorized" };
|
|
2176
2427
|
return;
|
|
2177
2428
|
}
|
|
2178
|
-
const tasks = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2429
|
+
const tasks = await strapi.documents(CONTENT_TYPE$1).findMany({
|
|
2179
2430
|
filters: { adminUserId },
|
|
2180
2431
|
sort: { createdAt: "desc" }
|
|
2181
2432
|
});
|
|
2182
2433
|
ctx.body = { data: tasks };
|
|
2183
2434
|
},
|
|
2184
2435
|
async create(ctx) {
|
|
2185
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2436
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2186
2437
|
if (!adminUserId) {
|
|
2187
2438
|
ctx.status = 401;
|
|
2188
2439
|
ctx.body = { error: "Unauthorized" };
|
|
2189
2440
|
return;
|
|
2190
2441
|
}
|
|
2191
2442
|
const body = ctx.request.body;
|
|
2192
|
-
const task2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2443
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).create({
|
|
2193
2444
|
data: {
|
|
2194
2445
|
title: body.title,
|
|
2195
2446
|
description: body.description,
|
|
@@ -2206,14 +2457,14 @@ const taskController = ({ strapi }) => ({
|
|
|
2206
2457
|
ctx.body = { data: task2 };
|
|
2207
2458
|
},
|
|
2208
2459
|
async update(ctx) {
|
|
2209
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2460
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2210
2461
|
if (!adminUserId) {
|
|
2211
2462
|
ctx.status = 401;
|
|
2212
2463
|
ctx.body = { error: "Unauthorized" };
|
|
2213
2464
|
return;
|
|
2214
2465
|
}
|
|
2215
2466
|
const { id } = ctx.params;
|
|
2216
|
-
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2467
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({
|
|
2217
2468
|
documentId: id
|
|
2218
2469
|
});
|
|
2219
2470
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2226,13 +2477,80 @@ const taskController = ({ strapi }) => ({
|
|
|
2226
2477
|
for (const key of ["title", "description", "content", "done", "priority", "consequence", "impact", "dueDate"]) {
|
|
2227
2478
|
if (body[key] !== void 0) data[key] = body[key];
|
|
2228
2479
|
}
|
|
2229
|
-
const task2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2480
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).update({
|
|
2230
2481
|
documentId: id,
|
|
2231
2482
|
data
|
|
2232
2483
|
});
|
|
2233
2484
|
ctx.body = { data: task2 };
|
|
2234
2485
|
},
|
|
2235
2486
|
async delete(ctx) {
|
|
2487
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2488
|
+
if (!adminUserId) {
|
|
2489
|
+
ctx.status = 401;
|
|
2490
|
+
ctx.body = { error: "Unauthorized" };
|
|
2491
|
+
return;
|
|
2492
|
+
}
|
|
2493
|
+
const { id } = ctx.params;
|
|
2494
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({
|
|
2495
|
+
documentId: id
|
|
2496
|
+
});
|
|
2497
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2498
|
+
ctx.status = 404;
|
|
2499
|
+
ctx.body = { error: "Task not found" };
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
await strapi.documents(CONTENT_TYPE$1).delete({ documentId: id });
|
|
2503
|
+
ctx.status = 200;
|
|
2504
|
+
ctx.body = { data: { documentId: id } };
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
|
+
const CONTENT_TYPE = "plugin::ai-sdk.note";
|
|
2508
|
+
function getAdminUserId(ctx) {
|
|
2509
|
+
const id = ctx.state?.user?.id;
|
|
2510
|
+
return typeof id === "number" ? id : null;
|
|
2511
|
+
}
|
|
2512
|
+
const noteController = ({ strapi }) => ({
|
|
2513
|
+
async find(ctx) {
|
|
2514
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2515
|
+
if (!adminUserId) {
|
|
2516
|
+
ctx.status = 401;
|
|
2517
|
+
ctx.body = { error: "Unauthorized" };
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
const notes = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2521
|
+
filters: { adminUserId },
|
|
2522
|
+
fields: ["title", "content", "category", "tags", "source", "createdAt"],
|
|
2523
|
+
sort: { createdAt: "desc" }
|
|
2524
|
+
});
|
|
2525
|
+
ctx.body = { data: notes };
|
|
2526
|
+
},
|
|
2527
|
+
async create(ctx) {
|
|
2528
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2529
|
+
if (!adminUserId) {
|
|
2530
|
+
ctx.status = 401;
|
|
2531
|
+
ctx.body = { error: "Unauthorized" };
|
|
2532
|
+
return;
|
|
2533
|
+
}
|
|
2534
|
+
const { title, content, category, tags, source } = ctx.request.body;
|
|
2535
|
+
if (!content || typeof content !== "string") {
|
|
2536
|
+
ctx.status = 400;
|
|
2537
|
+
ctx.body = { error: "content is required" };
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
const note2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2541
|
+
data: {
|
|
2542
|
+
title: title || "",
|
|
2543
|
+
content,
|
|
2544
|
+
category: category || "research",
|
|
2545
|
+
tags: tags || "",
|
|
2546
|
+
source: source || "",
|
|
2547
|
+
adminUserId
|
|
2548
|
+
}
|
|
2549
|
+
});
|
|
2550
|
+
ctx.status = 201;
|
|
2551
|
+
ctx.body = { data: note2 };
|
|
2552
|
+
},
|
|
2553
|
+
async update(ctx) {
|
|
2236
2554
|
const adminUserId = getAdminUserId(ctx);
|
|
2237
2555
|
if (!adminUserId) {
|
|
2238
2556
|
ctx.status = 401;
|
|
@@ -2245,12 +2563,58 @@ const taskController = ({ strapi }) => ({
|
|
|
2245
2563
|
});
|
|
2246
2564
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2247
2565
|
ctx.status = 404;
|
|
2248
|
-
ctx.body = { error: "
|
|
2566
|
+
ctx.body = { error: "Note not found" };
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
const { title, content, category, tags, source } = ctx.request.body;
|
|
2570
|
+
const data = {};
|
|
2571
|
+
if (title !== void 0) data.title = title;
|
|
2572
|
+
if (content !== void 0) data.content = content;
|
|
2573
|
+
if (category !== void 0) data.category = category;
|
|
2574
|
+
if (tags !== void 0) data.tags = tags;
|
|
2575
|
+
if (source !== void 0) data.source = source;
|
|
2576
|
+
const note2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2577
|
+
documentId: id,
|
|
2578
|
+
data
|
|
2579
|
+
});
|
|
2580
|
+
ctx.body = { data: note2 };
|
|
2581
|
+
},
|
|
2582
|
+
async delete(ctx) {
|
|
2583
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2584
|
+
if (!adminUserId) {
|
|
2585
|
+
ctx.status = 401;
|
|
2586
|
+
ctx.body = { error: "Unauthorized" };
|
|
2587
|
+
return;
|
|
2588
|
+
}
|
|
2589
|
+
const { id } = ctx.params;
|
|
2590
|
+
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2591
|
+
documentId: id
|
|
2592
|
+
});
|
|
2593
|
+
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2594
|
+
ctx.status = 404;
|
|
2595
|
+
ctx.body = { error: "Note not found" };
|
|
2249
2596
|
return;
|
|
2250
2597
|
}
|
|
2251
2598
|
await strapi.documents(CONTENT_TYPE).delete({ documentId: id });
|
|
2252
2599
|
ctx.status = 200;
|
|
2253
2600
|
ctx.body = { data: { documentId: id } };
|
|
2601
|
+
},
|
|
2602
|
+
async clearAll(ctx) {
|
|
2603
|
+
const adminUserId = getAdminUserId(ctx);
|
|
2604
|
+
if (!adminUserId) {
|
|
2605
|
+
ctx.status = 401;
|
|
2606
|
+
ctx.body = { error: "Unauthorized" };
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
const notes = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2610
|
+
filters: { adminUserId },
|
|
2611
|
+
fields: ["documentId"]
|
|
2612
|
+
});
|
|
2613
|
+
for (const note2 of notes) {
|
|
2614
|
+
await strapi.documents(CONTENT_TYPE).delete({ documentId: note2.documentId });
|
|
2615
|
+
}
|
|
2616
|
+
ctx.status = 200;
|
|
2617
|
+
ctx.body = { data: { deleted: notes.length } };
|
|
2254
2618
|
}
|
|
2255
2619
|
});
|
|
2256
2620
|
const controllers = {
|
|
@@ -2259,7 +2623,8 @@ const controllers = {
|
|
|
2259
2623
|
conversation: conversationController,
|
|
2260
2624
|
memory: memoryController,
|
|
2261
2625
|
"public-memory": publicMemoryController,
|
|
2262
|
-
task: taskController
|
|
2626
|
+
task: taskController,
|
|
2627
|
+
note: noteController
|
|
2263
2628
|
};
|
|
2264
2629
|
const promptInjection = [
|
|
2265
2630
|
"ignore (all |any )?(previous|prior|above) (instructions|prompts|rules)",
|
|
@@ -2629,6 +2994,36 @@ const adminAPIRoutes = {
|
|
|
2629
2994
|
path: "/tasks/:id",
|
|
2630
2995
|
handler: "task.delete",
|
|
2631
2996
|
config: { policies: [] }
|
|
2997
|
+
},
|
|
2998
|
+
{
|
|
2999
|
+
method: "GET",
|
|
3000
|
+
path: "/notes",
|
|
3001
|
+
handler: "note.find",
|
|
3002
|
+
config: { policies: [] }
|
|
3003
|
+
},
|
|
3004
|
+
{
|
|
3005
|
+
method: "POST",
|
|
3006
|
+
path: "/notes",
|
|
3007
|
+
handler: "note.create",
|
|
3008
|
+
config: { policies: [] }
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
method: "PUT",
|
|
3012
|
+
path: "/notes/:id",
|
|
3013
|
+
handler: "note.update",
|
|
3014
|
+
config: { policies: [] }
|
|
3015
|
+
},
|
|
3016
|
+
{
|
|
3017
|
+
method: "DELETE",
|
|
3018
|
+
path: "/notes/clear",
|
|
3019
|
+
handler: "note.clearAll",
|
|
3020
|
+
config: { policies: [] }
|
|
3021
|
+
},
|
|
3022
|
+
{
|
|
3023
|
+
method: "DELETE",
|
|
3024
|
+
path: "/notes/:id",
|
|
3025
|
+
handler: "note.delete",
|
|
3026
|
+
config: { policies: [] }
|
|
2632
3027
|
}
|
|
2633
3028
|
]
|
|
2634
3029
|
};
|
|
@@ -2716,6 +3111,26 @@ function describeTools(tools) {
|
|
|
2716
3111
|
return `Available tools:
|
|
2717
3112
|
${lines.join("\n")}`;
|
|
2718
3113
|
}
|
|
3114
|
+
function trimMessages(messages, max) {
|
|
3115
|
+
if (messages.length <= max) return messages;
|
|
3116
|
+
const sliced = messages.slice(-max);
|
|
3117
|
+
while (sliced.length > 0 && hasOrphanedToolCalls(sliced[0])) {
|
|
3118
|
+
sliced.shift();
|
|
3119
|
+
}
|
|
3120
|
+
return sliced;
|
|
3121
|
+
}
|
|
3122
|
+
function hasOrphanedToolCalls(message) {
|
|
3123
|
+
if (message.role !== "assistant") return false;
|
|
3124
|
+
if (message.parts) {
|
|
3125
|
+
return message.parts.some(
|
|
3126
|
+
(part) => part.type === "tool-invocation"
|
|
3127
|
+
);
|
|
3128
|
+
}
|
|
3129
|
+
if (message.toolInvocations?.length) {
|
|
3130
|
+
return true;
|
|
3131
|
+
}
|
|
3132
|
+
return false;
|
|
3133
|
+
}
|
|
2719
3134
|
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.
|
|
2720
3135
|
|
|
2721
3136
|
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.
|
|
@@ -2779,7 +3194,7 @@ const service = ({ strapi }) => {
|
|
|
2779
3194
|
const maxMessages = config2?.maxConversationMessages ?? DEFAULT_MAX_CONVERSATION_MESSAGES;
|
|
2780
3195
|
const maxOutputTokens = config2?.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
|
|
2781
3196
|
const maxSteps = config2?.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
2782
|
-
const trimmedMessages = messages
|
|
3197
|
+
const trimmedMessages = trimMessages(messages, maxMessages);
|
|
2783
3198
|
const modelMessages = await convertToModelMessages(trimmedMessages);
|
|
2784
3199
|
const tools = createTools(strapi, { adminUserId: options2?.adminUserId, enabledToolSources: options2?.enabledToolSources });
|
|
2785
3200
|
const toolsDescription = describeTools(tools);
|
|
@@ -2824,7 +3239,7 @@ ${lines.join("\n")}`;
|
|
|
2824
3239
|
const publicModel = publicConfig?.chatModel ?? DEFAULT_PUBLIC_CHAT_MODEL;
|
|
2825
3240
|
const allowedContentTypes = publicConfig?.allowedContentTypes ?? [];
|
|
2826
3241
|
const publicToolSources = publicConfig?.publicToolSources;
|
|
2827
|
-
const trimmedMessages = messages
|
|
3242
|
+
const trimmedMessages = trimMessages(messages, maxMessages);
|
|
2828
3243
|
const modelMessages = await convertToModelMessages(trimmedMessages);
|
|
2829
3244
|
const tools = createPublicTools(strapi, allowedContentTypes, publicToolSources);
|
|
2830
3245
|
const toolsDescription = describeTools(tools);
|