@yysng/ai-edit-engine 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/package.json +33 -0
- package/src/engine/api/ai-edit.js +45 -0
- package/src/engine/api/ai-generate.js +112 -0
- package/src/engine/index.js +2 -0
- package/src/engine/permissions/ai/permission.json +11 -0
- package/src/index.js +1 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yysng/ai-edit-engine",
|
|
3
|
+
"version": "2.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "AI Editing Engine for Astro sites (generation, validation, content mutation, Cloudflare-safe)",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./ui": "./src/ui/index.js",
|
|
10
|
+
"./api": "./src/api/index.js",
|
|
11
|
+
"./schemas": "./src/schemas/index.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"openai": "^6.13.0",
|
|
18
|
+
"zod": "^3.23.8"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"astro": "^5.0.0",
|
|
22
|
+
"@yysng/astro-boilerplate": "^1.1.36"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"astro",
|
|
26
|
+
"ai",
|
|
27
|
+
"cms",
|
|
28
|
+
"content-engine",
|
|
29
|
+
"cloudflare",
|
|
30
|
+
"ai-editor"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT"
|
|
33
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const prerender = false;
|
|
2
|
+
|
|
3
|
+
import * as Engine from "@yysng/astro-boilerplate";
|
|
4
|
+
|
|
5
|
+
const { updateContent } = Engine;
|
|
6
|
+
|
|
7
|
+
// --------------------------------------------------
|
|
8
|
+
// 🧠 ENGINE API (used by npm consumers)
|
|
9
|
+
// --------------------------------------------------
|
|
10
|
+
export async function editContent({ section, content, env = {} }) {
|
|
11
|
+
if (!section || !content) {
|
|
12
|
+
throw new Error("Missing section or content");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return updateContent(section, content, env);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// --------------------------------------------------
|
|
19
|
+
// 🌐 ASTRO ENDPOINT (used by playground / client site)
|
|
20
|
+
// --------------------------------------------------
|
|
21
|
+
export async function POST({ request, locals }) {
|
|
22
|
+
try {
|
|
23
|
+
const body = await request.json();
|
|
24
|
+
const { section, content } = body;
|
|
25
|
+
|
|
26
|
+
const result = await editContent({
|
|
27
|
+
section,
|
|
28
|
+
content,
|
|
29
|
+
env: locals?.runtime?.env
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return new Response(
|
|
33
|
+
JSON.stringify({ success: true, updated: section, result }),
|
|
34
|
+
{ status: 200 }
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error("AI Edit Error:", error);
|
|
39
|
+
|
|
40
|
+
return new Response(
|
|
41
|
+
JSON.stringify({ error: "Internal error", message: error.message }),
|
|
42
|
+
{ status: 500 }
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export const prerender = false;
|
|
2
|
+
|
|
3
|
+
import OpenAI from "openai";
|
|
4
|
+
|
|
5
|
+
// --------------------------------------------------
|
|
6
|
+
// 🧠 ENGINE API (used by npm consumers)
|
|
7
|
+
// --------------------------------------------------
|
|
8
|
+
export async function generateContent({ instruction, section, env = {} }) {
|
|
9
|
+
if (!instruction || typeof instruction !== "string") {
|
|
10
|
+
throw new Error("Invalid instruction");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const client = new OpenAI({
|
|
14
|
+
apiKey: env.OPENAI_API_KEY
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// ------------------------------
|
|
18
|
+
// CTA GENERATION
|
|
19
|
+
// ------------------------------
|
|
20
|
+
if (section === "cta") {
|
|
21
|
+
const prompt = `
|
|
22
|
+
You are an AI editor responsible for updating the CTA section of a website.
|
|
23
|
+
|
|
24
|
+
Rules:
|
|
25
|
+
- Output JSON only
|
|
26
|
+
- Follow the schema exactly
|
|
27
|
+
- Prefer partial updates
|
|
28
|
+
- Do not invent fields
|
|
29
|
+
|
|
30
|
+
Return JSON ONLY in this exact format:
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
"heading": string,
|
|
34
|
+
"description": string,
|
|
35
|
+
"button": {
|
|
36
|
+
"label": string,
|
|
37
|
+
"href": string
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
User instruction:
|
|
42
|
+
${instruction}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
const completion = await client.chat.completions.create({
|
|
46
|
+
model: "gpt-4o-mini",
|
|
47
|
+
messages: [{ role: "user", content: prompt }],
|
|
48
|
+
temperature: 0.7
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return JSON.parse(completion.choices[0].message.content);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ------------------------------
|
|
55
|
+
// HERO GENERATION
|
|
56
|
+
// ------------------------------
|
|
57
|
+
const heroPrompt = `
|
|
58
|
+
You are an AI editor responsible for updating the hero section of a website.
|
|
59
|
+
|
|
60
|
+
Rules:
|
|
61
|
+
- Output JSON only
|
|
62
|
+
- Follow the schema exactly
|
|
63
|
+
- Prefer partial updates
|
|
64
|
+
- Do not invent fields
|
|
65
|
+
|
|
66
|
+
Return JSON ONLY in this exact format:
|
|
67
|
+
|
|
68
|
+
{
|
|
69
|
+
"title": string,
|
|
70
|
+
"subtitle": string,
|
|
71
|
+
"cta": {
|
|
72
|
+
"label": string,
|
|
73
|
+
"href": string
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
User instruction:
|
|
78
|
+
${instruction}
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
const completion = await client.chat.completions.create({
|
|
82
|
+
model: "gpt-4o-mini",
|
|
83
|
+
messages: [{ role: "user", content: heroPrompt }],
|
|
84
|
+
temperature: 0.7
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return JSON.parse(completion.choices[0].message.content);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// --------------------------------------------------
|
|
91
|
+
// 🌐 ASTRO ENDPOINT (used by playground / client site)
|
|
92
|
+
// --------------------------------------------------
|
|
93
|
+
export async function POST({ request, locals }) {
|
|
94
|
+
try {
|
|
95
|
+
const { instruction, section } = await request.json();
|
|
96
|
+
|
|
97
|
+
const result = await generateContent({
|
|
98
|
+
instruction,
|
|
99
|
+
section,
|
|
100
|
+
env: locals?.runtime?.env
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return new Response(JSON.stringify(result), { status: 200 });
|
|
104
|
+
|
|
105
|
+
} catch (err) {
|
|
106
|
+
console.error("AI generate error:", err);
|
|
107
|
+
return new Response(
|
|
108
|
+
JSON.stringify({ error: "AI generation failed", message: err.message }),
|
|
109
|
+
{ status: 500 }
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./engine/index.js";
|