strapi-plugin-ai-sdk 0.7.4 → 0.7.9
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-CEEsJsKL.js → App-DTbAnq7K.js} +712 -53
- package/dist/_chunks/{App-DCV7o6Hc.mjs → App-DZVBmpvs.mjs} +714 -55
- package/dist/_chunks/{index-Cw2aiQ8K.js → index-C3xn2IND.js} +1 -1
- package/dist/_chunks/{index-BMrDQVQl.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 +603 -171
- package/dist/server/index.mjs +603 -171
- 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/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 +27 -0
- package/dist/server/src/tool-logic/find-one-content.d.ts +1 -1
- package/dist/server/src/tool-logic/index.d.ts +8 -2
- 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 +29 -0
- package/dist/server/src/tool-logic/upload-media.d.ts +1 -1
- package/dist/server/src/tools/definitions/create-content.d.ts +2 -0
- package/dist/server/src/tools/definitions/{write-content.d.ts → recall-notes.d.ts} +1 -1
- package/dist/server/src/tools/definitions/save-note.d.ts +2 -0
- package/dist/server/src/tools/definitions/update-content.d.ts +2 -0
- package/package.json +1 -1
- package/dist/server/src/tool-logic/write-content.d.ts +0 -34
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",
|
|
@@ -367,33 +470,41 @@ async function searchContent(strapi, params) {
|
|
|
367
470
|
}
|
|
368
471
|
};
|
|
369
472
|
}
|
|
370
|
-
const
|
|
473
|
+
const createContentSchema = z.object({
|
|
371
474
|
contentType: z.string().describe('Content type UID, e.g. "api::article.article"'),
|
|
372
|
-
action: z.enum(["create", "update"]).describe("Whether to create a new document or update an existing one"),
|
|
373
|
-
documentId: z.string().optional().describe("Required for update — the document ID to update"),
|
|
374
475
|
data: z.record(z.string(), z.unknown()).describe("The field values to set. Must match the content type schema."),
|
|
375
476
|
status: z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
376
477
|
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
377
478
|
});
|
|
378
|
-
const
|
|
379
|
-
async function
|
|
380
|
-
const { contentType,
|
|
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.";
|
|
480
|
+
async function createContent(strapi, params) {
|
|
481
|
+
const { contentType, data, status, locale } = params;
|
|
381
482
|
if (!strapi.contentTypes[contentType]) {
|
|
382
483
|
throw new Error(`Content type "${contentType}" does not exist.`);
|
|
383
484
|
}
|
|
384
|
-
if (action === "update" && !documentId) {
|
|
385
|
-
throw new Error("documentId is required for update actions.");
|
|
386
|
-
}
|
|
387
485
|
const docs = strapi.documents(contentType);
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
486
|
+
const document = await docs.create({
|
|
487
|
+
data,
|
|
488
|
+
...status ? { status } : {},
|
|
489
|
+
...locale ? { locale } : {},
|
|
490
|
+
populate: "*"
|
|
491
|
+
});
|
|
492
|
+
return { action: "create", document };
|
|
493
|
+
}
|
|
494
|
+
const updateContentSchema = z.object({
|
|
495
|
+
contentType: z.string().describe('Content type UID, e.g. "api::article.article"'),
|
|
496
|
+
documentId: z.string().describe("The document ID to update"),
|
|
497
|
+
data: z.record(z.string(), z.unknown()).describe("The field values to set. Must match the content type schema."),
|
|
498
|
+
status: z.enum(["draft", "published"]).optional().describe("Document status. Defaults to draft."),
|
|
499
|
+
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
500
|
+
});
|
|
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.";
|
|
502
|
+
async function updateContent(strapi, params) {
|
|
503
|
+
const { contentType, documentId, data, status, locale } = params;
|
|
504
|
+
if (!strapi.contentTypes[contentType]) {
|
|
505
|
+
throw new Error(`Content type "${contentType}" does not exist.`);
|
|
396
506
|
}
|
|
507
|
+
const docs = strapi.documents(contentType);
|
|
397
508
|
const existing = await docs.findOne({
|
|
398
509
|
documentId,
|
|
399
510
|
...locale ? { locale } : {}
|
|
@@ -460,7 +571,7 @@ async function sendEmail(strapi, params) {
|
|
|
460
571
|
subject: params.subject
|
|
461
572
|
};
|
|
462
573
|
}
|
|
463
|
-
const CONTENT_TYPE$
|
|
574
|
+
const CONTENT_TYPE$a = "plugin::ai-sdk.memory";
|
|
464
575
|
const saveMemorySchema = z.object({
|
|
465
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")'),
|
|
466
577
|
category: z.string().optional().describe('Category for the memory (e.g. "preference", "project", "personal", "general"). Defaults to "general".')
|
|
@@ -471,7 +582,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
471
582
|
return { success: false, message: "Cannot save memory: user context not available." };
|
|
472
583
|
}
|
|
473
584
|
try {
|
|
474
|
-
await strapi.documents(CONTENT_TYPE$
|
|
585
|
+
await strapi.documents(CONTENT_TYPE$a).create({
|
|
475
586
|
data: {
|
|
476
587
|
content: params.content,
|
|
477
588
|
category: params.category || "general",
|
|
@@ -484,7 +595,7 @@ async function saveMemory(strapi, params, context) {
|
|
|
484
595
|
return { success: false, message: `Failed to save memory: ${detail}` };
|
|
485
596
|
}
|
|
486
597
|
}
|
|
487
|
-
const CONTENT_TYPE$
|
|
598
|
+
const CONTENT_TYPE$9 = "plugin::ai-sdk.memory";
|
|
488
599
|
const recallMemoriesSchema = z.object({
|
|
489
600
|
query: z.string().optional().describe("Optional search term to filter memories by content"),
|
|
490
601
|
category: z.string().optional().describe('Optional category to filter by (e.g. "preference", "project", "personal")')
|
|
@@ -502,7 +613,7 @@ async function recallMemories(strapi, params, context) {
|
|
|
502
613
|
if (params.query) {
|
|
503
614
|
filters.content = { $containsi: params.query };
|
|
504
615
|
}
|
|
505
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
616
|
+
const memories = await strapi.documents(CONTENT_TYPE$9).findMany({
|
|
506
617
|
filters,
|
|
507
618
|
fields: ["content", "category"],
|
|
508
619
|
sort: { createdAt: "desc" }
|
|
@@ -528,7 +639,7 @@ const findOneContentSchema = z.object({
|
|
|
528
639
|
status: z.enum(["draft", "published"]).optional().describe("Document status filter."),
|
|
529
640
|
locale: z.string().optional().describe('Locale code for i18n content, e.g. "en" or "fr"')
|
|
530
641
|
});
|
|
531
|
-
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.";
|
|
532
643
|
async function findOneContent(strapi, params) {
|
|
533
644
|
const { contentType, documentId, populate = "*", fields, status, locale } = params;
|
|
534
645
|
if (!strapi.contentTypes[contentType]) {
|
|
@@ -554,7 +665,7 @@ const uploadMediaSchema = z.object({
|
|
|
554
665
|
caption: z.string().optional().describe("Caption for the media file"),
|
|
555
666
|
alternativeText: z.string().optional().describe("Alternative text for accessibility")
|
|
556
667
|
});
|
|
557
|
-
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.";
|
|
558
669
|
async function uploadMedia(strapi, params) {
|
|
559
670
|
const { url, name, caption, alternativeText } = params;
|
|
560
671
|
let parsedUrl;
|
|
@@ -622,10 +733,10 @@ async function uploadMedia(strapi, params) {
|
|
|
622
733
|
return {
|
|
623
734
|
file: uploadedFile,
|
|
624
735
|
message: `File "${uploadedFile.name}" uploaded successfully (ID: ${uploadedFile.id}).`,
|
|
625
|
-
usage: `To link this file to a content type field, use
|
|
736
|
+
usage: `To link this file to a content type field, use createContent or updateContent with: { "fieldName": ${uploadedFile.id} }`
|
|
626
737
|
};
|
|
627
738
|
}
|
|
628
|
-
const CONTENT_TYPE$
|
|
739
|
+
const CONTENT_TYPE$8 = "plugin::ai-sdk.public-memory";
|
|
629
740
|
const recallPublicMemoriesSchema = z.object({
|
|
630
741
|
query: z.string().optional().describe("Optional search term to filter public memories by content"),
|
|
631
742
|
category: z.string().optional().describe('Optional category to filter by (e.g. "faq", "product", "policy")')
|
|
@@ -636,7 +747,7 @@ async function recallPublicMemories(strapi, params) {
|
|
|
636
747
|
const filters = {};
|
|
637
748
|
if (params.category) filters.category = params.category;
|
|
638
749
|
if (params.query) filters.content = { $containsi: params.query };
|
|
639
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
750
|
+
const memories = await strapi.documents(CONTENT_TYPE$8).findMany({
|
|
640
751
|
filters,
|
|
641
752
|
fields: ["content", "category"],
|
|
642
753
|
sort: { createdAt: "desc" }
|
|
@@ -718,7 +829,7 @@ const aggregateContentSchema = z.object({
|
|
|
718
829
|
status: z.enum(["draft", "published"]).optional().describe("Filter by document status"),
|
|
719
830
|
locale: z.string().optional().describe("Locale code for i18n content")
|
|
720
831
|
});
|
|
721
|
-
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.';
|
|
722
833
|
function buildBaseQuery(params) {
|
|
723
834
|
const { filters, status, locale, dateFrom, dateTo, dateField = "createdAt" } = params;
|
|
724
835
|
const query = {};
|
|
@@ -870,7 +981,7 @@ async function aggregateContent(strapi, params) {
|
|
|
870
981
|
throw new Error(`Unknown operation: ${operation}`);
|
|
871
982
|
}
|
|
872
983
|
}
|
|
873
|
-
const CONTENT_TYPE$
|
|
984
|
+
const CONTENT_TYPE$7 = "plugin::ai-sdk.task";
|
|
874
985
|
const manageTaskSchema = z.object({
|
|
875
986
|
action: z.enum(["create", "update", "complete", "list", "summary"]).describe(
|
|
876
987
|
"Action to perform: create a new task, update an existing task, complete (mark done), list open tasks, or get a summary."
|
|
@@ -886,14 +997,14 @@ const manageTaskSchema = z.object({
|
|
|
886
997
|
done: z.boolean().optional().describe("Set done status explicitly (for update action)."),
|
|
887
998
|
filters: z.record(z.string(), z.unknown()).optional().describe("Additional Strapi filters for list action.")
|
|
888
999
|
});
|
|
889
|
-
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.";
|
|
890
1001
|
async function resolveTask(strapi, adminUserId, documentId, title) {
|
|
891
1002
|
if (documentId) {
|
|
892
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1003
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).findOne({ documentId });
|
|
893
1004
|
if (task2 && task2.adminUserId === adminUserId) return task2;
|
|
894
1005
|
}
|
|
895
1006
|
if (title) {
|
|
896
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1007
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
897
1008
|
filters: {
|
|
898
1009
|
adminUserId,
|
|
899
1010
|
title: { $containsi: title }
|
|
@@ -946,7 +1057,7 @@ async function manageTask(strapi, params, context) {
|
|
|
946
1057
|
if (params.consequence !== void 0) data.consequence = params.consequence;
|
|
947
1058
|
if (params.impact !== void 0) data.impact = params.impact;
|
|
948
1059
|
if (params.dueDate !== void 0) data.dueDate = params.dueDate;
|
|
949
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1060
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
950
1061
|
documentId: duplicate.documentId,
|
|
951
1062
|
data
|
|
952
1063
|
});
|
|
@@ -957,7 +1068,7 @@ async function manageTask(strapi, params, context) {
|
|
|
957
1068
|
data: updated
|
|
958
1069
|
};
|
|
959
1070
|
}
|
|
960
|
-
const task2 = await strapi.documents(CONTENT_TYPE$
|
|
1071
|
+
const task2 = await strapi.documents(CONTENT_TYPE$7).create({
|
|
961
1072
|
data: {
|
|
962
1073
|
title: params.title,
|
|
963
1074
|
description: params.description,
|
|
@@ -986,7 +1097,7 @@ async function manageTask(strapi, params, context) {
|
|
|
986
1097
|
for (const key of ["title", "description", "content", "priority", "consequence", "impact", "dueDate", "done"]) {
|
|
987
1098
|
if (params[key] !== void 0) data[key] = params[key];
|
|
988
1099
|
}
|
|
989
|
-
const updated = await strapi.documents(CONTENT_TYPE$
|
|
1100
|
+
const updated = await strapi.documents(CONTENT_TYPE$7).update({
|
|
990
1101
|
documentId: existing.documentId,
|
|
991
1102
|
data
|
|
992
1103
|
});
|
|
@@ -997,7 +1108,7 @@ async function manageTask(strapi, params, context) {
|
|
|
997
1108
|
if (!toComplete) {
|
|
998
1109
|
return { success: false, message: "Task not found. Provide a documentId or a title to search by." };
|
|
999
1110
|
}
|
|
1000
|
-
await strapi.documents(CONTENT_TYPE$
|
|
1111
|
+
await strapi.documents(CONTENT_TYPE$7).update({
|
|
1001
1112
|
documentId: toComplete.documentId,
|
|
1002
1113
|
data: { done: true }
|
|
1003
1114
|
});
|
|
@@ -1009,7 +1120,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1009
1120
|
done: false,
|
|
1010
1121
|
...params.filters
|
|
1011
1122
|
};
|
|
1012
|
-
const tasks = await strapi.documents(CONTENT_TYPE$
|
|
1123
|
+
const tasks = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1013
1124
|
filters
|
|
1014
1125
|
});
|
|
1015
1126
|
const sorted = tasks.sort((a, b) => {
|
|
@@ -1038,7 +1149,7 @@ async function manageTask(strapi, params, context) {
|
|
|
1038
1149
|
};
|
|
1039
1150
|
}
|
|
1040
1151
|
case "summary": {
|
|
1041
|
-
const allOpen = await strapi.documents(CONTENT_TYPE$
|
|
1152
|
+
const allOpen = await strapi.documents(CONTENT_TYPE$7).findMany({
|
|
1042
1153
|
filters: { adminUserId, done: false }
|
|
1043
1154
|
});
|
|
1044
1155
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -1075,6 +1186,82 @@ async function manageTask(strapi, params, context) {
|
|
|
1075
1186
|
return { success: false, message: `Task operation failed: ${detail}` };
|
|
1076
1187
|
}
|
|
1077
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
|
+
}
|
|
1078
1265
|
const listContentTypesTool = {
|
|
1079
1266
|
name: "listContentTypes",
|
|
1080
1267
|
description: listContentTypesDescription,
|
|
@@ -1123,13 +1310,24 @@ async function sanitizeInput(strapi, uid, data, auth) {
|
|
|
1123
1310
|
throw error;
|
|
1124
1311
|
}
|
|
1125
1312
|
}
|
|
1126
|
-
const
|
|
1127
|
-
name: "
|
|
1128
|
-
description:
|
|
1129
|
-
schema:
|
|
1313
|
+
const createContentTool = {
|
|
1314
|
+
name: "createContent",
|
|
1315
|
+
description: createContentDescription,
|
|
1316
|
+
schema: createContentSchema,
|
|
1317
|
+
execute: async (args, strapi) => {
|
|
1318
|
+
const sanitizedData = await sanitizeInput(strapi, args.contentType, args.data);
|
|
1319
|
+
const result = await createContent(strapi, { ...args, data: sanitizedData });
|
|
1320
|
+
const sanitizedDoc = await sanitizeOutput(strapi, args.contentType, result.document);
|
|
1321
|
+
return { ...result, document: sanitizedDoc };
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
const updateContentTool = {
|
|
1325
|
+
name: "updateContent",
|
|
1326
|
+
description: updateContentDescription,
|
|
1327
|
+
schema: updateContentSchema,
|
|
1130
1328
|
execute: async (args, strapi) => {
|
|
1131
1329
|
const sanitizedData = await sanitizeInput(strapi, args.contentType, args.data);
|
|
1132
|
-
const result = await
|
|
1330
|
+
const result = await updateContent(strapi, { ...args, data: sanitizedData });
|
|
1133
1331
|
const sanitizedDoc = await sanitizeOutput(strapi, args.contentType, result.document);
|
|
1134
1332
|
return { ...result, document: sanitizedDoc };
|
|
1135
1333
|
}
|
|
@@ -1194,10 +1392,25 @@ const manageTaskTool = {
|
|
|
1194
1392
|
execute: async (args, strapi, context) => manageTask(strapi, args, context),
|
|
1195
1393
|
internal: true
|
|
1196
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
|
+
};
|
|
1197
1409
|
const builtInTools = [
|
|
1198
1410
|
listContentTypesTool,
|
|
1199
1411
|
searchContentTool,
|
|
1200
|
-
|
|
1412
|
+
createContentTool,
|
|
1413
|
+
updateContentTool,
|
|
1201
1414
|
findOneContentTool,
|
|
1202
1415
|
uploadMediaTool,
|
|
1203
1416
|
sendEmailTool,
|
|
@@ -1205,12 +1418,22 @@ const builtInTools = [
|
|
|
1205
1418
|
recallMemoriesTool,
|
|
1206
1419
|
recallPublicMemoriesTool,
|
|
1207
1420
|
aggregateContentTool,
|
|
1208
|
-
manageTaskTool
|
|
1421
|
+
manageTaskTool,
|
|
1422
|
+
saveNoteTool,
|
|
1423
|
+
recallNotesTool
|
|
1209
1424
|
];
|
|
1210
1425
|
const PLUGIN_ID$2 = "ai-sdk";
|
|
1211
1426
|
const bootstrap = ({ strapi }) => {
|
|
1212
1427
|
const plugin = strapi.plugin(PLUGIN_ID$2);
|
|
1213
1428
|
const config2 = strapi.config.get(`plugin::${PLUGIN_ID$2}`);
|
|
1429
|
+
initializeProvider(strapi, plugin, config2);
|
|
1430
|
+
const registry = initializeToolRegistry(plugin);
|
|
1431
|
+
discoverPluginTools(strapi, registry);
|
|
1432
|
+
plugin.createMcpServer = () => createMcpServer(strapi);
|
|
1433
|
+
plugin.mcpSessions = /* @__PURE__ */ new Map();
|
|
1434
|
+
strapi.log.info(`[${PLUGIN_ID$2}] MCP endpoint available at: /api/${PLUGIN_ID$2}/mcp`);
|
|
1435
|
+
};
|
|
1436
|
+
function initializeProvider(strapi, plugin, config2) {
|
|
1214
1437
|
AIProvider.registerProvider("anthropic", ({ apiKey, baseURL }) => {
|
|
1215
1438
|
const provider = createAnthropic({ apiKey, baseURL });
|
|
1216
1439
|
return (modelId) => provider(modelId);
|
|
@@ -1223,27 +1446,22 @@ const bootstrap = ({ strapi }) => {
|
|
|
1223
1446
|
} else {
|
|
1224
1447
|
strapi.log.warn(`[${PLUGIN_ID$2}] anthropicApiKey not configured, AI provider will not be available`);
|
|
1225
1448
|
}
|
|
1449
|
+
}
|
|
1450
|
+
function initializeToolRegistry(plugin) {
|
|
1226
1451
|
const toolRegistry = new ToolRegistry();
|
|
1227
1452
|
for (const tool2 of builtInTools) {
|
|
1228
1453
|
toolRegistry.register(tool2);
|
|
1229
1454
|
}
|
|
1230
1455
|
plugin.toolRegistry = toolRegistry;
|
|
1456
|
+
return toolRegistry;
|
|
1457
|
+
}
|
|
1458
|
+
function discoverPluginTools(strapi, registry) {
|
|
1231
1459
|
const pluginNames = Object.keys(strapi.plugins).filter((n) => n !== PLUGIN_ID$2);
|
|
1232
1460
|
strapi.log.info(`[${PLUGIN_ID$2}] Scanning ${pluginNames.length} plugins for ai-tools: [${pluginNames.join(", ")}]`);
|
|
1233
1461
|
for (const [pluginName, pluginInstance] of Object.entries(strapi.plugins)) {
|
|
1234
1462
|
if (pluginName === PLUGIN_ID$2) continue;
|
|
1235
1463
|
try {
|
|
1236
|
-
|
|
1237
|
-
try {
|
|
1238
|
-
aiToolsService = strapi.plugin(pluginName)?.service?.("ai-tools");
|
|
1239
|
-
} catch {
|
|
1240
|
-
}
|
|
1241
|
-
if (!aiToolsService) {
|
|
1242
|
-
try {
|
|
1243
|
-
aiToolsService = pluginInstance.service?.("ai-tools");
|
|
1244
|
-
} catch {
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1464
|
+
const aiToolsService = resolveAiToolsService(strapi, pluginName, pluginInstance);
|
|
1247
1465
|
if (!aiToolsService?.getTools) {
|
|
1248
1466
|
strapi.log.debug(`[${PLUGIN_ID$2}] No ai-tools service on plugin: ${pluginName}`);
|
|
1249
1467
|
continue;
|
|
@@ -1251,21 +1469,7 @@ const bootstrap = ({ strapi }) => {
|
|
|
1251
1469
|
strapi.log.info(`[${PLUGIN_ID$2}] Found ai-tools service on plugin: ${pluginName}`);
|
|
1252
1470
|
const contributed = aiToolsService.getTools();
|
|
1253
1471
|
if (!Array.isArray(contributed)) continue;
|
|
1254
|
-
|
|
1255
|
-
for (const tool2 of contributed) {
|
|
1256
|
-
if (!tool2.name || !tool2.execute || !tool2.schema) {
|
|
1257
|
-
strapi.log.warn(`[${PLUGIN_ID$2}] Invalid tool from ${pluginName}: ${tool2.name || "unnamed"}`);
|
|
1258
|
-
continue;
|
|
1259
|
-
}
|
|
1260
|
-
const safeName = pluginName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1261
|
-
const namespacedName = `${safeName}__${tool2.name}`;
|
|
1262
|
-
if (toolRegistry.has(namespacedName)) {
|
|
1263
|
-
strapi.log.warn(`[${PLUGIN_ID$2}] Duplicate tool: ${namespacedName}`);
|
|
1264
|
-
continue;
|
|
1265
|
-
}
|
|
1266
|
-
toolRegistry.register({ ...tool2, name: namespacedName });
|
|
1267
|
-
count++;
|
|
1268
|
-
}
|
|
1472
|
+
const count = registerContributedTools(strapi, registry, pluginName, contributed);
|
|
1269
1473
|
if (count > 0) {
|
|
1270
1474
|
strapi.log.info(`[${PLUGIN_ID$2}] Registered ${count} tools from plugin: ${pluginName}`);
|
|
1271
1475
|
}
|
|
@@ -1273,10 +1477,38 @@ const bootstrap = ({ strapi }) => {
|
|
|
1273
1477
|
strapi.log.warn(`[${PLUGIN_ID$2}] Tool discovery failed for ${pluginName}: ${err}`);
|
|
1274
1478
|
}
|
|
1275
1479
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1480
|
+
}
|
|
1481
|
+
function registerContributedTools(strapi, registry, pluginName, tools) {
|
|
1482
|
+
const safeName = pluginName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1483
|
+
let count = 0;
|
|
1484
|
+
for (const tool2 of tools) {
|
|
1485
|
+
if (!tool2.name || !tool2.execute || !tool2.schema) {
|
|
1486
|
+
strapi.log.warn(`[${PLUGIN_ID$2}] Invalid tool from ${pluginName}: ${tool2.name || "unnamed"}`);
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
const namespacedName = `${safeName}__${tool2.name}`;
|
|
1490
|
+
if (registry.has(namespacedName)) {
|
|
1491
|
+
strapi.log.warn(`[${PLUGIN_ID$2}] Duplicate tool: ${namespacedName}`);
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
registry.register({ ...tool2, name: namespacedName });
|
|
1495
|
+
count++;
|
|
1496
|
+
}
|
|
1497
|
+
return count;
|
|
1498
|
+
}
|
|
1499
|
+
function resolveAiToolsService(strapi, pluginName, pluginInstance) {
|
|
1500
|
+
try {
|
|
1501
|
+
const svc = strapi.plugin(pluginName)?.service?.("ai-tools");
|
|
1502
|
+
if (svc) return svc;
|
|
1503
|
+
} catch {
|
|
1504
|
+
}
|
|
1505
|
+
try {
|
|
1506
|
+
const svc = pluginInstance.service?.("ai-tools");
|
|
1507
|
+
if (svc) return svc;
|
|
1508
|
+
} catch {
|
|
1509
|
+
}
|
|
1510
|
+
return null;
|
|
1511
|
+
}
|
|
1280
1512
|
const PLUGIN_ID$1 = "ai-sdk";
|
|
1281
1513
|
async function closeSession(strapi, sessionId, session) {
|
|
1282
1514
|
try {
|
|
@@ -1359,17 +1591,17 @@ const config = {
|
|
|
1359
1591
|
}
|
|
1360
1592
|
}
|
|
1361
1593
|
};
|
|
1362
|
-
const kind$
|
|
1363
|
-
const collectionName$
|
|
1364
|
-
const info$
|
|
1594
|
+
const kind$4 = "collectionType";
|
|
1595
|
+
const collectionName$4 = "ai_sdk_conversations";
|
|
1596
|
+
const info$4 = {
|
|
1365
1597
|
singularName: "conversation",
|
|
1366
1598
|
pluralName: "conversations",
|
|
1367
1599
|
displayName: "AI Conversation"
|
|
1368
1600
|
};
|
|
1369
|
-
const options$
|
|
1601
|
+
const options$4 = {
|
|
1370
1602
|
draftAndPublish: false
|
|
1371
1603
|
};
|
|
1372
|
-
const pluginOptions$
|
|
1604
|
+
const pluginOptions$4 = {
|
|
1373
1605
|
"content-manager": {
|
|
1374
1606
|
visible: false
|
|
1375
1607
|
},
|
|
@@ -1377,7 +1609,7 @@ const pluginOptions$3 = {
|
|
|
1377
1609
|
visible: false
|
|
1378
1610
|
}
|
|
1379
1611
|
};
|
|
1380
|
-
const attributes$
|
|
1612
|
+
const attributes$4 = {
|
|
1381
1613
|
title: {
|
|
1382
1614
|
type: "string",
|
|
1383
1615
|
required: true,
|
|
@@ -1392,26 +1624,26 @@ const attributes$3 = {
|
|
|
1392
1624
|
required: true
|
|
1393
1625
|
}
|
|
1394
1626
|
};
|
|
1395
|
-
const schema$
|
|
1396
|
-
kind: kind$
|
|
1397
|
-
collectionName: collectionName$
|
|
1398
|
-
info: info$
|
|
1399
|
-
options: options$
|
|
1400
|
-
pluginOptions: pluginOptions$
|
|
1401
|
-
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
|
|
1402
1634
|
};
|
|
1403
|
-
const conversation = { schema: schema$
|
|
1404
|
-
const kind$
|
|
1405
|
-
const collectionName$
|
|
1406
|
-
const info$
|
|
1635
|
+
const conversation = { schema: schema$4 };
|
|
1636
|
+
const kind$3 = "collectionType";
|
|
1637
|
+
const collectionName$3 = "ai_sdk_memories";
|
|
1638
|
+
const info$3 = {
|
|
1407
1639
|
singularName: "memory",
|
|
1408
1640
|
pluralName: "memories",
|
|
1409
1641
|
displayName: "AI Memory"
|
|
1410
1642
|
};
|
|
1411
|
-
const options$
|
|
1643
|
+
const options$3 = {
|
|
1412
1644
|
draftAndPublish: false
|
|
1413
1645
|
};
|
|
1414
|
-
const pluginOptions$
|
|
1646
|
+
const pluginOptions$3 = {
|
|
1415
1647
|
"content-manager": {
|
|
1416
1648
|
visible: false
|
|
1417
1649
|
},
|
|
@@ -1419,9 +1651,9 @@ const pluginOptions$2 = {
|
|
|
1419
1651
|
visible: false
|
|
1420
1652
|
}
|
|
1421
1653
|
};
|
|
1422
|
-
const attributes$
|
|
1654
|
+
const attributes$3 = {
|
|
1423
1655
|
content: {
|
|
1424
|
-
type: "
|
|
1656
|
+
type: "richtext",
|
|
1425
1657
|
required: true
|
|
1426
1658
|
},
|
|
1427
1659
|
category: {
|
|
@@ -1439,26 +1671,26 @@ const attributes$2 = {
|
|
|
1439
1671
|
required: true
|
|
1440
1672
|
}
|
|
1441
1673
|
};
|
|
1442
|
-
const schema$
|
|
1443
|
-
kind: kind$
|
|
1444
|
-
collectionName: collectionName$
|
|
1445
|
-
info: info$
|
|
1446
|
-
options: options$
|
|
1447
|
-
pluginOptions: pluginOptions$
|
|
1448
|
-
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
|
|
1449
1681
|
};
|
|
1450
|
-
const memory = { schema: schema$
|
|
1451
|
-
const kind$
|
|
1452
|
-
const collectionName$
|
|
1453
|
-
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 = {
|
|
1454
1686
|
singularName: "public-memory",
|
|
1455
1687
|
pluralName: "public-memories",
|
|
1456
1688
|
displayName: "AI Public Memory"
|
|
1457
1689
|
};
|
|
1458
|
-
const options$
|
|
1690
|
+
const options$2 = {
|
|
1459
1691
|
draftAndPublish: false
|
|
1460
1692
|
};
|
|
1461
|
-
const pluginOptions$
|
|
1693
|
+
const pluginOptions$2 = {
|
|
1462
1694
|
"content-manager": {
|
|
1463
1695
|
visible: false
|
|
1464
1696
|
},
|
|
@@ -1466,7 +1698,7 @@ const pluginOptions$1 = {
|
|
|
1466
1698
|
visible: false
|
|
1467
1699
|
}
|
|
1468
1700
|
};
|
|
1469
|
-
const attributes$
|
|
1701
|
+
const attributes$2 = {
|
|
1470
1702
|
content: {
|
|
1471
1703
|
type: "text",
|
|
1472
1704
|
required: true
|
|
@@ -1482,26 +1714,26 @@ const attributes$1 = {
|
|
|
1482
1714
|
"default": "general"
|
|
1483
1715
|
}
|
|
1484
1716
|
};
|
|
1485
|
-
const schema$
|
|
1486
|
-
kind: kind$
|
|
1487
|
-
collectionName: collectionName$
|
|
1488
|
-
info: info$
|
|
1489
|
-
options: options$
|
|
1490
|
-
pluginOptions: pluginOptions$
|
|
1491
|
-
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
|
|
1492
1724
|
};
|
|
1493
|
-
const publicMemory = { schema: schema$
|
|
1494
|
-
const kind = "collectionType";
|
|
1495
|
-
const collectionName = "ai_sdk_tasks";
|
|
1496
|
-
const info = {
|
|
1725
|
+
const publicMemory = { schema: schema$2 };
|
|
1726
|
+
const kind$1 = "collectionType";
|
|
1727
|
+
const collectionName$1 = "ai_sdk_tasks";
|
|
1728
|
+
const info$1 = {
|
|
1497
1729
|
singularName: "task",
|
|
1498
1730
|
pluralName: "tasks",
|
|
1499
1731
|
displayName: "AI Task"
|
|
1500
1732
|
};
|
|
1501
|
-
const options = {
|
|
1733
|
+
const options$1 = {
|
|
1502
1734
|
draftAndPublish: false
|
|
1503
1735
|
};
|
|
1504
|
-
const pluginOptions = {
|
|
1736
|
+
const pluginOptions$1 = {
|
|
1505
1737
|
"content-manager": {
|
|
1506
1738
|
visible: true
|
|
1507
1739
|
},
|
|
@@ -1509,7 +1741,7 @@ const pluginOptions = {
|
|
|
1509
1741
|
visible: false
|
|
1510
1742
|
}
|
|
1511
1743
|
};
|
|
1512
|
-
const attributes = {
|
|
1744
|
+
const attributes$1 = {
|
|
1513
1745
|
title: {
|
|
1514
1746
|
type: "string",
|
|
1515
1747
|
required: true
|
|
@@ -1554,6 +1786,62 @@ const attributes = {
|
|
|
1554
1786
|
required: true
|
|
1555
1787
|
}
|
|
1556
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
|
+
};
|
|
1557
1845
|
const schema = {
|
|
1558
1846
|
kind,
|
|
1559
1847
|
collectionName,
|
|
@@ -1562,8 +1850,8 @@ const schema = {
|
|
|
1562
1850
|
pluginOptions,
|
|
1563
1851
|
attributes
|
|
1564
1852
|
};
|
|
1565
|
-
const
|
|
1566
|
-
const contentTypes = { conversation, memory, "public-memory": publicMemory, task };
|
|
1853
|
+
const note = { schema };
|
|
1854
|
+
const contentTypes = { conversation, memory, "public-memory": publicMemory, task, note };
|
|
1567
1855
|
function getService(strapi, ctx) {
|
|
1568
1856
|
const service2 = strapi.plugin("ai-sdk").service("service");
|
|
1569
1857
|
if (!service2.isInitialized()) {
|
|
@@ -1879,20 +2167,20 @@ const mcpController = ({ strapi }) => {
|
|
|
1879
2167
|
}
|
|
1880
2168
|
};
|
|
1881
2169
|
};
|
|
1882
|
-
const CONTENT_TYPE$
|
|
1883
|
-
function getAdminUserId$
|
|
2170
|
+
const CONTENT_TYPE$4 = "plugin::ai-sdk.conversation";
|
|
2171
|
+
function getAdminUserId$3(ctx) {
|
|
1884
2172
|
const id = ctx.state?.user?.id;
|
|
1885
2173
|
return typeof id === "number" ? id : null;
|
|
1886
2174
|
}
|
|
1887
2175
|
const conversationController = ({ strapi }) => ({
|
|
1888
2176
|
async find(ctx) {
|
|
1889
|
-
const adminUserId = getAdminUserId$
|
|
2177
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1890
2178
|
if (!adminUserId) {
|
|
1891
2179
|
ctx.status = 401;
|
|
1892
2180
|
ctx.body = { error: "Unauthorized" };
|
|
1893
2181
|
return;
|
|
1894
2182
|
}
|
|
1895
|
-
const conversations = await strapi.documents(CONTENT_TYPE$
|
|
2183
|
+
const conversations = await strapi.documents(CONTENT_TYPE$4).findMany({
|
|
1896
2184
|
filters: { adminUserId },
|
|
1897
2185
|
fields: ["title", "createdAt", "updatedAt"],
|
|
1898
2186
|
sort: { updatedAt: "desc" }
|
|
@@ -1900,14 +2188,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1900
2188
|
ctx.body = { data: conversations };
|
|
1901
2189
|
},
|
|
1902
2190
|
async findOne(ctx) {
|
|
1903
|
-
const adminUserId = getAdminUserId$
|
|
2191
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1904
2192
|
if (!adminUserId) {
|
|
1905
2193
|
ctx.status = 401;
|
|
1906
2194
|
ctx.body = { error: "Unauthorized" };
|
|
1907
2195
|
return;
|
|
1908
2196
|
}
|
|
1909
2197
|
const { id } = ctx.params;
|
|
1910
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2198
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1911
2199
|
documentId: id
|
|
1912
2200
|
});
|
|
1913
2201
|
if (!conversation2 || conversation2.adminUserId !== adminUserId) {
|
|
@@ -1918,14 +2206,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1918
2206
|
ctx.body = { data: conversation2 };
|
|
1919
2207
|
},
|
|
1920
2208
|
async create(ctx) {
|
|
1921
|
-
const adminUserId = getAdminUserId$
|
|
2209
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1922
2210
|
if (!adminUserId) {
|
|
1923
2211
|
ctx.status = 401;
|
|
1924
2212
|
ctx.body = { error: "Unauthorized" };
|
|
1925
2213
|
return;
|
|
1926
2214
|
}
|
|
1927
2215
|
const { title, messages } = ctx.request.body;
|
|
1928
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2216
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).create({
|
|
1929
2217
|
data: {
|
|
1930
2218
|
title: title || "New conversation",
|
|
1931
2219
|
messages: messages || [],
|
|
@@ -1936,14 +2224,14 @@ const conversationController = ({ strapi }) => ({
|
|
|
1936
2224
|
ctx.body = { data: conversation2 };
|
|
1937
2225
|
},
|
|
1938
2226
|
async update(ctx) {
|
|
1939
|
-
const adminUserId = getAdminUserId$
|
|
2227
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1940
2228
|
if (!adminUserId) {
|
|
1941
2229
|
ctx.status = 401;
|
|
1942
2230
|
ctx.body = { error: "Unauthorized" };
|
|
1943
2231
|
return;
|
|
1944
2232
|
}
|
|
1945
2233
|
const { id } = ctx.params;
|
|
1946
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2234
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1947
2235
|
documentId: id
|
|
1948
2236
|
});
|
|
1949
2237
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1955,21 +2243,21 @@ const conversationController = ({ strapi }) => ({
|
|
|
1955
2243
|
const data = {};
|
|
1956
2244
|
if (title !== void 0) data.title = title;
|
|
1957
2245
|
if (messages !== void 0) data.messages = messages;
|
|
1958
|
-
const conversation2 = await strapi.documents(CONTENT_TYPE$
|
|
2246
|
+
const conversation2 = await strapi.documents(CONTENT_TYPE$4).update({
|
|
1959
2247
|
documentId: id,
|
|
1960
2248
|
data
|
|
1961
2249
|
});
|
|
1962
2250
|
ctx.body = { data: conversation2 };
|
|
1963
2251
|
},
|
|
1964
2252
|
async delete(ctx) {
|
|
1965
|
-
const adminUserId = getAdminUserId$
|
|
2253
|
+
const adminUserId = getAdminUserId$3(ctx);
|
|
1966
2254
|
if (!adminUserId) {
|
|
1967
2255
|
ctx.status = 401;
|
|
1968
2256
|
ctx.body = { error: "Unauthorized" };
|
|
1969
2257
|
return;
|
|
1970
2258
|
}
|
|
1971
2259
|
const { id } = ctx.params;
|
|
1972
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2260
|
+
const existing = await strapi.documents(CONTENT_TYPE$4).findOne({
|
|
1973
2261
|
documentId: id
|
|
1974
2262
|
});
|
|
1975
2263
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -1977,25 +2265,25 @@ const conversationController = ({ strapi }) => ({
|
|
|
1977
2265
|
ctx.body = { error: "Conversation not found" };
|
|
1978
2266
|
return;
|
|
1979
2267
|
}
|
|
1980
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2268
|
+
await strapi.documents(CONTENT_TYPE$4).delete({ documentId: id });
|
|
1981
2269
|
ctx.status = 200;
|
|
1982
2270
|
ctx.body = { data: { documentId: id } };
|
|
1983
2271
|
}
|
|
1984
2272
|
});
|
|
1985
|
-
const CONTENT_TYPE$
|
|
1986
|
-
function getAdminUserId$
|
|
2273
|
+
const CONTENT_TYPE$3 = "plugin::ai-sdk.memory";
|
|
2274
|
+
function getAdminUserId$2(ctx) {
|
|
1987
2275
|
const id = ctx.state?.user?.id;
|
|
1988
2276
|
return typeof id === "number" ? id : null;
|
|
1989
2277
|
}
|
|
1990
2278
|
const memoryController = ({ strapi }) => ({
|
|
1991
2279
|
async find(ctx) {
|
|
1992
|
-
const adminUserId = getAdminUserId$
|
|
2280
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
1993
2281
|
if (!adminUserId) {
|
|
1994
2282
|
ctx.status = 401;
|
|
1995
2283
|
ctx.body = { error: "Unauthorized" };
|
|
1996
2284
|
return;
|
|
1997
2285
|
}
|
|
1998
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2286
|
+
const memories = await strapi.documents(CONTENT_TYPE$3).findMany({
|
|
1999
2287
|
filters: { adminUserId },
|
|
2000
2288
|
fields: ["content", "category", "createdAt"],
|
|
2001
2289
|
sort: { createdAt: "desc" }
|
|
@@ -2003,7 +2291,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2003
2291
|
ctx.body = { data: memories };
|
|
2004
2292
|
},
|
|
2005
2293
|
async create(ctx) {
|
|
2006
|
-
const adminUserId = getAdminUserId$
|
|
2294
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2007
2295
|
if (!adminUserId) {
|
|
2008
2296
|
ctx.status = 401;
|
|
2009
2297
|
ctx.body = { error: "Unauthorized" };
|
|
@@ -2015,7 +2303,7 @@ const memoryController = ({ strapi }) => ({
|
|
|
2015
2303
|
ctx.body = { error: "content is required" };
|
|
2016
2304
|
return;
|
|
2017
2305
|
}
|
|
2018
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2306
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).create({
|
|
2019
2307
|
data: {
|
|
2020
2308
|
content,
|
|
2021
2309
|
category: category || "general",
|
|
@@ -2026,14 +2314,14 @@ const memoryController = ({ strapi }) => ({
|
|
|
2026
2314
|
ctx.body = { data: memory2 };
|
|
2027
2315
|
},
|
|
2028
2316
|
async update(ctx) {
|
|
2029
|
-
const adminUserId = getAdminUserId$
|
|
2317
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2030
2318
|
if (!adminUserId) {
|
|
2031
2319
|
ctx.status = 401;
|
|
2032
2320
|
ctx.body = { error: "Unauthorized" };
|
|
2033
2321
|
return;
|
|
2034
2322
|
}
|
|
2035
2323
|
const { id } = ctx.params;
|
|
2036
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2324
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2037
2325
|
documentId: id
|
|
2038
2326
|
});
|
|
2039
2327
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2045,21 +2333,21 @@ const memoryController = ({ strapi }) => ({
|
|
|
2045
2333
|
const data = {};
|
|
2046
2334
|
if (content !== void 0) data.content = content;
|
|
2047
2335
|
if (category !== void 0) data.category = category;
|
|
2048
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2336
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$3).update({
|
|
2049
2337
|
documentId: id,
|
|
2050
2338
|
data
|
|
2051
2339
|
});
|
|
2052
2340
|
ctx.body = { data: memory2 };
|
|
2053
2341
|
},
|
|
2054
2342
|
async delete(ctx) {
|
|
2055
|
-
const adminUserId = getAdminUserId$
|
|
2343
|
+
const adminUserId = getAdminUserId$2(ctx);
|
|
2056
2344
|
if (!adminUserId) {
|
|
2057
2345
|
ctx.status = 401;
|
|
2058
2346
|
ctx.body = { error: "Unauthorized" };
|
|
2059
2347
|
return;
|
|
2060
2348
|
}
|
|
2061
2349
|
const { id } = ctx.params;
|
|
2062
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2350
|
+
const existing = await strapi.documents(CONTENT_TYPE$3).findOne({
|
|
2063
2351
|
documentId: id
|
|
2064
2352
|
});
|
|
2065
2353
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2067,15 +2355,15 @@ const memoryController = ({ strapi }) => ({
|
|
|
2067
2355
|
ctx.body = { error: "Memory not found" };
|
|
2068
2356
|
return;
|
|
2069
2357
|
}
|
|
2070
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2358
|
+
await strapi.documents(CONTENT_TYPE$3).delete({ documentId: id });
|
|
2071
2359
|
ctx.status = 200;
|
|
2072
2360
|
ctx.body = { data: { documentId: id } };
|
|
2073
2361
|
}
|
|
2074
2362
|
});
|
|
2075
|
-
const CONTENT_TYPE$
|
|
2363
|
+
const CONTENT_TYPE$2 = "plugin::ai-sdk.public-memory";
|
|
2076
2364
|
const publicMemoryController = ({ strapi }) => ({
|
|
2077
2365
|
async find(ctx) {
|
|
2078
|
-
const memories = await strapi.documents(CONTENT_TYPE$
|
|
2366
|
+
const memories = await strapi.documents(CONTENT_TYPE$2).findMany({
|
|
2079
2367
|
fields: ["content", "category", "createdAt"],
|
|
2080
2368
|
sort: { createdAt: "desc" }
|
|
2081
2369
|
});
|
|
@@ -2088,7 +2376,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2088
2376
|
ctx.body = { error: "content is required" };
|
|
2089
2377
|
return;
|
|
2090
2378
|
}
|
|
2091
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2379
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).create({
|
|
2092
2380
|
data: { content, category: category || "general" }
|
|
2093
2381
|
});
|
|
2094
2382
|
ctx.status = 201;
|
|
@@ -2096,7 +2384,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2096
2384
|
},
|
|
2097
2385
|
async update(ctx) {
|
|
2098
2386
|
const { id } = ctx.params;
|
|
2099
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2387
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2100
2388
|
if (!existing) {
|
|
2101
2389
|
ctx.status = 404;
|
|
2102
2390
|
ctx.body = { error: "Public memory not found" };
|
|
@@ -2106,7 +2394,7 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2106
2394
|
const data = {};
|
|
2107
2395
|
if (content !== void 0) data.content = content;
|
|
2108
2396
|
if (category !== void 0) data.category = category;
|
|
2109
|
-
const memory2 = await strapi.documents(CONTENT_TYPE$
|
|
2397
|
+
const memory2 = await strapi.documents(CONTENT_TYPE$2).update({
|
|
2110
2398
|
documentId: id,
|
|
2111
2399
|
data
|
|
2112
2400
|
});
|
|
@@ -2114,45 +2402,45 @@ const publicMemoryController = ({ strapi }) => ({
|
|
|
2114
2402
|
},
|
|
2115
2403
|
async delete(ctx) {
|
|
2116
2404
|
const { id } = ctx.params;
|
|
2117
|
-
const existing = await strapi.documents(CONTENT_TYPE$
|
|
2405
|
+
const existing = await strapi.documents(CONTENT_TYPE$2).findOne({ documentId: id });
|
|
2118
2406
|
if (!existing) {
|
|
2119
2407
|
ctx.status = 404;
|
|
2120
2408
|
ctx.body = { error: "Public memory not found" };
|
|
2121
2409
|
return;
|
|
2122
2410
|
}
|
|
2123
|
-
await strapi.documents(CONTENT_TYPE$
|
|
2411
|
+
await strapi.documents(CONTENT_TYPE$2).delete({ documentId: id });
|
|
2124
2412
|
ctx.status = 200;
|
|
2125
2413
|
ctx.body = { data: { documentId: id } };
|
|
2126
2414
|
}
|
|
2127
2415
|
});
|
|
2128
|
-
const CONTENT_TYPE = "plugin::ai-sdk.task";
|
|
2129
|
-
function getAdminUserId(ctx) {
|
|
2416
|
+
const CONTENT_TYPE$1 = "plugin::ai-sdk.task";
|
|
2417
|
+
function getAdminUserId$1(ctx) {
|
|
2130
2418
|
const id = ctx.state?.user?.id;
|
|
2131
2419
|
return typeof id === "number" ? id : null;
|
|
2132
2420
|
}
|
|
2133
2421
|
const taskController = ({ strapi }) => ({
|
|
2134
2422
|
async find(ctx) {
|
|
2135
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2423
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2136
2424
|
if (!adminUserId) {
|
|
2137
2425
|
ctx.status = 401;
|
|
2138
2426
|
ctx.body = { error: "Unauthorized" };
|
|
2139
2427
|
return;
|
|
2140
2428
|
}
|
|
2141
|
-
const tasks = await strapi.documents(CONTENT_TYPE).findMany({
|
|
2429
|
+
const tasks = await strapi.documents(CONTENT_TYPE$1).findMany({
|
|
2142
2430
|
filters: { adminUserId },
|
|
2143
2431
|
sort: { createdAt: "desc" }
|
|
2144
2432
|
});
|
|
2145
2433
|
ctx.body = { data: tasks };
|
|
2146
2434
|
},
|
|
2147
2435
|
async create(ctx) {
|
|
2148
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2436
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2149
2437
|
if (!adminUserId) {
|
|
2150
2438
|
ctx.status = 401;
|
|
2151
2439
|
ctx.body = { error: "Unauthorized" };
|
|
2152
2440
|
return;
|
|
2153
2441
|
}
|
|
2154
2442
|
const body = ctx.request.body;
|
|
2155
|
-
const task2 = await strapi.documents(CONTENT_TYPE).create({
|
|
2443
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).create({
|
|
2156
2444
|
data: {
|
|
2157
2445
|
title: body.title,
|
|
2158
2446
|
description: body.description,
|
|
@@ -2169,14 +2457,14 @@ const taskController = ({ strapi }) => ({
|
|
|
2169
2457
|
ctx.body = { data: task2 };
|
|
2170
2458
|
},
|
|
2171
2459
|
async update(ctx) {
|
|
2172
|
-
const adminUserId = getAdminUserId(ctx);
|
|
2460
|
+
const adminUserId = getAdminUserId$1(ctx);
|
|
2173
2461
|
if (!adminUserId) {
|
|
2174
2462
|
ctx.status = 401;
|
|
2175
2463
|
ctx.body = { error: "Unauthorized" };
|
|
2176
2464
|
return;
|
|
2177
2465
|
}
|
|
2178
2466
|
const { id } = ctx.params;
|
|
2179
|
-
const existing = await strapi.documents(CONTENT_TYPE).findOne({
|
|
2467
|
+
const existing = await strapi.documents(CONTENT_TYPE$1).findOne({
|
|
2180
2468
|
documentId: id
|
|
2181
2469
|
});
|
|
2182
2470
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
@@ -2189,13 +2477,80 @@ const taskController = ({ strapi }) => ({
|
|
|
2189
2477
|
for (const key of ["title", "description", "content", "done", "priority", "consequence", "impact", "dueDate"]) {
|
|
2190
2478
|
if (body[key] !== void 0) data[key] = body[key];
|
|
2191
2479
|
}
|
|
2192
|
-
const task2 = await strapi.documents(CONTENT_TYPE).update({
|
|
2480
|
+
const task2 = await strapi.documents(CONTENT_TYPE$1).update({
|
|
2193
2481
|
documentId: id,
|
|
2194
2482
|
data
|
|
2195
2483
|
});
|
|
2196
2484
|
ctx.body = { data: task2 };
|
|
2197
2485
|
},
|
|
2198
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) {
|
|
2199
2554
|
const adminUserId = getAdminUserId(ctx);
|
|
2200
2555
|
if (!adminUserId) {
|
|
2201
2556
|
ctx.status = 401;
|
|
@@ -2208,12 +2563,58 @@ const taskController = ({ strapi }) => ({
|
|
|
2208
2563
|
});
|
|
2209
2564
|
if (!existing || existing.adminUserId !== adminUserId) {
|
|
2210
2565
|
ctx.status = 404;
|
|
2211
|
-
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" };
|
|
2212
2596
|
return;
|
|
2213
2597
|
}
|
|
2214
2598
|
await strapi.documents(CONTENT_TYPE).delete({ documentId: id });
|
|
2215
2599
|
ctx.status = 200;
|
|
2216
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 } };
|
|
2217
2618
|
}
|
|
2218
2619
|
});
|
|
2219
2620
|
const controllers = {
|
|
@@ -2222,7 +2623,8 @@ const controllers = {
|
|
|
2222
2623
|
conversation: conversationController,
|
|
2223
2624
|
memory: memoryController,
|
|
2224
2625
|
"public-memory": publicMemoryController,
|
|
2225
|
-
task: taskController
|
|
2626
|
+
task: taskController,
|
|
2627
|
+
note: noteController
|
|
2226
2628
|
};
|
|
2227
2629
|
const promptInjection = [
|
|
2228
2630
|
"ignore (all |any )?(previous|prior|above) (instructions|prompts|rules)",
|
|
@@ -2592,6 +2994,36 @@ const adminAPIRoutes = {
|
|
|
2592
2994
|
path: "/tasks/:id",
|
|
2593
2995
|
handler: "task.delete",
|
|
2594
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: [] }
|
|
2595
3027
|
}
|
|
2596
3028
|
]
|
|
2597
3029
|
};
|