@blinkk/root-cms 3.0.1-beta.5 → 3.0.1-beta.6
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/app.js +1 -1
- package/dist/{chunk-5CZBPART.js → chunk-VBIIJ22U.js} +20 -10
- package/dist/edit-MT4B37QK.js +7 -0
- package/dist/plugin.js +3 -1
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +154 -154
- package/package.json +3 -3
- package/dist/edit-XX3LAGK6.js +0 -7
package/dist/app.js
CHANGED
|
@@ -191,7 +191,7 @@ function createCmsTools(ctx) {
|
|
|
191
191
|
}
|
|
192
192
|
}),
|
|
193
193
|
doc_set: tool({
|
|
194
|
-
description: "Replace the entire draft fields payload of a CMS document. Pass the full JSON object that should become the new draft contents \u2014 any fields omitted will be removed. The payload is validated against the collection schema and the call is rejected on validation errors. Prefer `doc_updateField` for targeted edits. Only writes the draft version; users must publish separately. Always confirm with the user before calling.",
|
|
194
|
+
description: "Replace the entire draft fields payload of a CMS document. Pass the full JSON object that should become the new draft contents \u2014 any fields omitted will be removed. The payload is validated against the collection schema and the call is rejected on validation errors. Prefer `doc_updateField` for targeted edits. Only writes the draft version; users must publish separately. Always confirm with the user before calling. Format: pass plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",
|
|
195
195
|
inputSchema: z.object({
|
|
196
196
|
docId: z.string().describe(
|
|
197
197
|
'Full doc id in the form "Collection/slug" (e.g. "Pages/home").'
|
|
@@ -202,7 +202,7 @@ function createCmsTools(ctx) {
|
|
|
202
202
|
})
|
|
203
203
|
}),
|
|
204
204
|
doc_create: tool({
|
|
205
|
-
description: "Create a new draft CMS document with the given slug. Fails if the doc already exists. Pass optional initial fields (validated against the collection schema). Always confirm with the user before calling.",
|
|
205
|
+
description: "Create a new draft CMS document with the given slug. Fails if the doc already exists. Pass optional initial fields (validated against the collection schema). Always confirm with the user before calling. Format: pass plain JSON for `fields`. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",
|
|
206
206
|
inputSchema: z.object({
|
|
207
207
|
docId: z.string().describe(
|
|
208
208
|
'Full doc id in the form "Collection/slug" (e.g. "BlogPosts/my-new-post").'
|
|
@@ -211,7 +211,7 @@ function createCmsTools(ctx) {
|
|
|
211
211
|
})
|
|
212
212
|
}),
|
|
213
213
|
doc_updateField: tool({
|
|
214
|
-
description: 'Update a single field on a draft CMS document by JSON path. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths (e.g. "hero.title") and zero-based array indices. For example, update the first module title with path "content.modules.0.title". To append or remove array items, first read the current doc, then set the whole array path (e.g. "content.modules") to the updated array. The value is validated against the field schema and the call is rejected if the shape is wrong (e.g. passing a string to a richtext field). Only updates the draft version; users must publish separately. Always confirm with the user before calling.',
|
|
214
|
+
description: 'Update a single field on a draft CMS document by JSON path. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths (e.g. "hero.title") and zero-based array indices. For example, update the first module title with path "content.modules.0.title". To append or remove array items, first read the current doc, then set the whole array path (e.g. "content.modules") to the updated array. The value is validated against the field schema and the call is rejected if the shape is wrong (e.g. passing a string to a richtext field). Only updates the draft version; users must publish separately. Always confirm with the user before calling. Format: pass `value` as plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the value into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape and `blocks` MUST be a plain JSON array of `{type, data}` objects (never wrapped in `_array`).',
|
|
215
215
|
inputSchema: z.object({
|
|
216
216
|
docId: z.string(),
|
|
217
217
|
path: z.string().describe(
|
|
@@ -625,6 +625,14 @@ function buildCmsToolContext(options) {
|
|
|
625
625
|
}
|
|
626
626
|
};
|
|
627
627
|
}
|
|
628
|
+
function buildActiveDocPrompt(docId) {
|
|
629
|
+
return [
|
|
630
|
+
"Active document context:",
|
|
631
|
+
`- The user is currently viewing and editing the document \`${docId}\` in the CMS UI.`,
|
|
632
|
+
'- When the user refers to "this document", "this draft", "the current doc/page", or similar without naming a doc, they mean this document.',
|
|
633
|
+
"- Default to targeting this document for read and write tools unless the user explicitly names a different one."
|
|
634
|
+
].join("\n");
|
|
635
|
+
}
|
|
628
636
|
function buildExecutionModePrompt(mode) {
|
|
629
637
|
const common = [
|
|
630
638
|
"Root AI execution workflow:",
|
|
@@ -675,6 +683,7 @@ async function runChatStream(options) {
|
|
|
675
683
|
user,
|
|
676
684
|
chatId,
|
|
677
685
|
executionMode = "approve",
|
|
686
|
+
activeDocId,
|
|
678
687
|
loadCollection,
|
|
679
688
|
loadAllCollections
|
|
680
689
|
} = options;
|
|
@@ -694,10 +703,11 @@ async function runChatStream(options) {
|
|
|
694
703
|
"Be concise and use markdown for rich responses."
|
|
695
704
|
].join(" ");
|
|
696
705
|
const rootMd = await readRootMd(rootConfig.rootDir);
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
706
|
+
const promptSections = [basePrompt, "", buildExecutionModePrompt(executionMode)];
|
|
707
|
+
if (activeDocId) {
|
|
708
|
+
promptSections.push("", buildActiveDocPrompt(activeDocId));
|
|
709
|
+
}
|
|
710
|
+
const systemPrompt = buildSystemPrompt(promptSections.join("\n"), rootMd);
|
|
701
711
|
const modelMessages = await convertToModelMessages(messages, { tools });
|
|
702
712
|
const result = streamText({
|
|
703
713
|
model: languageModel,
|
|
@@ -749,7 +759,7 @@ async function runEditObjectStream(options) {
|
|
|
749
759
|
loadAllCollections
|
|
750
760
|
});
|
|
751
761
|
const tools = model.capabilities?.tools === false ? {} : createReadOnlyCmsTools(toolContext);
|
|
752
|
-
const editPromptText = (await import("./edit-
|
|
762
|
+
const editPromptText = (await import("./edit-MT4B37QK.js")).default;
|
|
753
763
|
const promptParts = [
|
|
754
764
|
stripLegacyEditOutputSpec(editPromptText),
|
|
755
765
|
"",
|
|
@@ -1003,7 +1013,7 @@ function extractJsonFromResponse(responseText) {
|
|
|
1003
1013
|
// package.json
|
|
1004
1014
|
var package_default = {
|
|
1005
1015
|
name: "@blinkk/root-cms",
|
|
1006
|
-
version: "3.0.1-beta.
|
|
1016
|
+
version: "3.0.1-beta.6",
|
|
1007
1017
|
author: "s@blinkk.com",
|
|
1008
1018
|
license: "MIT",
|
|
1009
1019
|
engines: {
|
|
@@ -1172,7 +1182,7 @@ var package_default = {
|
|
|
1172
1182
|
yjs: "13.6.27"
|
|
1173
1183
|
},
|
|
1174
1184
|
peerDependencies: {
|
|
1175
|
-
"@blinkk/root": "3.0.1-beta.
|
|
1185
|
+
"@blinkk/root": "3.0.1-beta.6",
|
|
1176
1186
|
"firebase-admin": ">=11",
|
|
1177
1187
|
"firebase-functions": ">=4"
|
|
1178
1188
|
},
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./chunk-MLKGABMK.js";
|
|
2
|
+
|
|
3
|
+
// shared/ai/prompts/edit.txt
|
|
4
|
+
var edit_default = 'Role: You are a highly accurate AI assistant specializing in converting unstructured documents into JSON files compatible with Root CMS. Root CMS is a web-based CMS for building websites and landing pages, storing its content as JSON files in a Firebase Firestore database.\n\nObjective: To edit and/or generate highly accurate JSON files compatible with Root CMS, based on user input (screenshots, chat messages, etc.) and, when editing JSON files, the original JSON file you are editing. The resulting content should contain all of the marketing content provided by the user input (and none of the annotations or superfluous content). The JSON files should be perfectly compatible with Root CMS.\n\nInput Requirements & Handling:\n\n- You will receive unstructured documents and you must convert them into JSON files compatible with Root CMS by either editing the existing JSON files or generating new ones from scratch. The JSON files you produce will typically represent a single section of a page of the website, such as a hero section, a feature section, or a footer.\n\n- When editing an existing JSON file, it will be annotated with a key `_type` that indicates the type of section it is, such as `Hero`, `Feature`, or `Footer`. You must ensure that the resulting JSON file is compatible with Root CMS and contains all of the marketing content provided by the user input. You will also be given a TypeScript interface in `root-cms.d.ts` that describes the structure of the JSON file you are editing. You must ensure that the resulting JSON file is compatible with this interface.\n\n- The input you receive will be broken into three parts. (1) `root-cms-d.ts` (the TypeScript interface), (2) the existing JSON file you are editing (or an empty JSON file when generating new content), and (3) the user input (screenshots, chat messages, instructions, etc.). You must ensure that the resulting JSON file is compatible with the structure defined by the TypeScript interface and contains all of the marketing content provided by the user input.\n\n- When you provide your response, if the user instructs you to only edit one part of the original JSON, make sure to leave the rest of the JSON file untouched. You must return the entire JSON document after applying changes. Never omit, rename, reorder or invent top-level keys. Copy all unmodified fields exactly as they appear in the input.\n\nRoot CMS JSON File Structure:\n\n- Root CMS JSON files are standard JSON files described by the TypeScript interface in `root-cms.d.ts`. However, there is one critical syntax rule that you must understand and always follow regarding array values. Array values are expressed as hash maps. The order of the resulting data when Root CMS unmarshals the data is provided by a special key called `_array`. For example, to represent an array [1, 2, 3] in the CMS, the JSON data may look like this. You may generate your own UIDs for the keys and the items within `_array`.\n\n```json\n{\n "_array": ["2HGwoV", "LjFHWk", "OLakGA", "UaGHJh"],\n "2HGwoV": 1,\n "LjFHWk": 2,\n "OLakGA": 3,\n "UaGHJh": 4\n}\n```\n\nWhen creating arrays in your JSON output, you must _never_ forget to add an `_array` key. If you forget to add an `_array` key, the output will NOT work with Root CMS. When adding new array items, you can create your own array keys.\n\nThe ONE exception to this rule is the `blocks` array inside a Rich Text field (see #3 below). Rich Text data is stored as-is and is NOT marshaled, so `blocks` MUST always be a plain JSON array, never an `_array` object. Wrapping rich text `blocks` in `_array` notation will corrupt the data when it is saved.\n\n2. Images and file fields have system-provided metadata, that looks like this example:\n\n```\n{\n "src": "https://storage.googleapis.com/rootjs-dev.appspot.com/www/uploads/2cad5d65bb7690bad5dcd4a041cf2fef46361678.svg",\n "filename": "600x400.svg",\n "uploadedAt": "1754023634564",\n "alt": "",\n "width": "600",\n "uploadedBy": "user@example.com",\n "height": "400"\n}\n```\n\n3. Rich Text fields are stored as Editor.js / Lexical documents, which look like this. You may generate your own UIDs for the `id` fields. Note that `blocks` MUST be a plain JSON array \u2014 do NOT use the `_array` object notation here.\n\n```\n{\n "version": "2.28.2",\n "time": 1754024041637,\n "blocks": [\n {\n "type": "paragraph",\n "data": {\n "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <a href=\\"https://example.com\\">This accepts HTML</a>."\n },\n "id": "_8PEf3kBx2"\n },\n {\n "data": {\n "style": "unordered",\n "items": [\n {\n "content": "This is list item 1.",\n "items": []\n },\n {\n "items": [],\n "content": "This is list item 2."\n }\n ]\n },\n "id": "G5zMDP1ytM",\n "type": "unorderedList"\n }\n ]\n}\n```\n\n4. Root CMS supports "oneOf" fields, where values can be "one of" another schema. These are typically used as array values or object values, where the user can from one of other schema types to structure the data value. For example, each module in a page\'s module list is "one of" the modules available in the library. One of values have a system-provided `_type` key that describes the type of the value. For example, this is a hero module, whose type is "TemplateHeadline", one of the available templates from the module library:\n\n```\n{\n "eyebrow": "Lorem ipsum",\n "_type": "TemplateHeadline",\n "body": {\n "time": 1754023554170,\n "version": "2.28.2",\n "blocks": [\n {\n "type": "paragraph",\n "data": {\n "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."\n },\n "id": "IVmxEVsxmt"\n },\n {\n "id": "aMiHiywkQD",\n "type": "paragraph",\n "data": {\n "text": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."\n }\n }\n ]\n },\n "title": "Welcome to our website"\n}\n```\n\nWhen adding new items to arrays that use `oneOf` fields, try your best to figure out which content type would best satisfy the user\'s request. You must never _invent_ new content types, for example, if "TemplateFoo" doesn\'t exist in `root-cms.d.ts`, you must never add a value with `{"_type": "TemplateFoo"}`. If none of the available content types within `root-cms.d.ts` satisfy the user\'s request, avoid creating the new array item and inform the user that there is no existing template compatible.\n\nAdditionally, when adding new items to existing JSON data, you must carefully check the structure of those items as defined by `root-cms.d.ts`. Avoid inventing new fields for content types, use only those defined by the `root-cms.d.ts`. For example, if you are adding a button to a module, carefully check the button structure defined in `root-cms.d.ts` and only populate fields that are defined there.\n\nFinally, when you provide your response, it MUST be structured in the following way for handling by the chat client.\n\n{\n "data": <The JSON data generated by you via the instructions above>,\n "message": <A brief message that describes what you did.>\n}\n\nYou must always ONLY reply in this exact format. The brief message that describes what you did should be written succinctly, tersely, in a friendly but not cute tone, and be no more than a sentence or two.\n';
|
|
5
|
+
export {
|
|
6
|
+
edit_default as default
|
|
7
|
+
};
|
package/dist/plugin.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
serializeAiConfig,
|
|
13
13
|
summarizeDiff,
|
|
14
14
|
translateString
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VBIIJ22U.js";
|
|
16
16
|
import {
|
|
17
17
|
runCronJobs
|
|
18
18
|
} from "./chunk-BGTUWIV6.js";
|
|
@@ -553,6 +553,7 @@ function api(server, options) {
|
|
|
553
553
|
return;
|
|
554
554
|
}
|
|
555
555
|
const executionMode = normalizeExecutionMode(body.executionMode);
|
|
556
|
+
const activeDocId = typeof body.docId === "string" && body.docId.trim() ? body.docId.trim() : void 0;
|
|
556
557
|
const cmsClient = new RootCMSClient(req.rootConfig);
|
|
557
558
|
const store = new ChatStore(cmsClient, req.user.email);
|
|
558
559
|
const requestedChatId = typeof body.chatId === "string" ? body.chatId.trim() : "";
|
|
@@ -593,6 +594,7 @@ function api(server, options) {
|
|
|
593
594
|
chatId,
|
|
594
595
|
user: req.user.email,
|
|
595
596
|
executionMode,
|
|
597
|
+
activeDocId,
|
|
596
598
|
loadCollection: (collectionId) => getCollectionSchema(req, collectionId),
|
|
597
599
|
loadAllCollections: async () => (await options.getRenderer(req)).getCollections()
|
|
598
600
|
});
|