@davia/agent 0.1.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/LICENSE +21 -0
- package/dist/agent/agent.d.ts +13 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +40 -0
- package/dist/agent/context.d.ts +9 -0
- package/dist/agent/context.d.ts.map +1 -0
- package/dist/agent/context.js +7 -0
- package/dist/agent/helpers/initialization.d.ts +30 -0
- package/dist/agent/helpers/initialization.d.ts.map +1 -0
- package/dist/agent/helpers/initialization.js +247 -0
- package/dist/agent/helpers/messages-caching-handler.d.ts +14 -0
- package/dist/agent/helpers/messages-caching-handler.d.ts.map +1 -0
- package/dist/agent/helpers/messages-caching-handler.js +162 -0
- package/dist/agent/helpers/tools.d.ts +46 -0
- package/dist/agent/helpers/tools.d.ts.map +1 -0
- package/dist/agent/helpers/tools.js +164 -0
- package/dist/agent/helpers/tree.d.ts +15 -0
- package/dist/agent/helpers/tree.d.ts.map +1 -0
- package/dist/agent/helpers/tree.js +146 -0
- package/dist/agent/middlewares/after-model.d.ts +6 -0
- package/dist/agent/middlewares/after-model.d.ts.map +1 -0
- package/dist/agent/middlewares/after-model.js +19 -0
- package/dist/agent/middlewares/initialization.d.ts +17 -0
- package/dist/agent/middlewares/initialization.d.ts.map +1 -0
- package/dist/agent/middlewares/initialization.js +93 -0
- package/dist/agent/prompts/agent.d.ts +9 -0
- package/dist/agent/prompts/agent.d.ts.map +1 -0
- package/dist/agent/prompts/agent.js +151 -0
- package/dist/agent/prompts/blocks/data.d.ts +2 -0
- package/dist/agent/prompts/blocks/data.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/data.js +90 -0
- package/dist/agent/prompts/blocks/excalidraw.d.ts +2 -0
- package/dist/agent/prompts/blocks/excalidraw.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/excalidraw.js +52 -0
- package/dist/agent/prompts/blocks/file_handling.d.ts +2 -0
- package/dist/agent/prompts/blocks/file_handling.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/file_handling.js +29 -0
- package/dist/agent/prompts/blocks/mdx/available_packages.d.ts +2 -0
- package/dist/agent/prompts/blocks/mdx/available_packages.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/mdx/available_packages.js +8 -0
- package/dist/agent/prompts/blocks/mdx/custom_components.d.ts +2 -0
- package/dist/agent/prompts/blocks/mdx/custom_components.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/mdx/custom_components.js +77 -0
- package/dist/agent/prompts/blocks/mdx/davia_specific.d.ts +2 -0
- package/dist/agent/prompts/blocks/mdx/davia_specific.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/mdx/davia_specific.js +116 -0
- package/dist/agent/prompts/blocks/mdx/mdx.d.ts +2 -0
- package/dist/agent/prompts/blocks/mdx/mdx.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/mdx/mdx.js +91 -0
- package/dist/agent/prompts/blocks/mdx/shadcn.d.ts +2 -0
- package/dist/agent/prompts/blocks/mdx/shadcn.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/mdx/shadcn.js +132 -0
- package/dist/agent/prompts/blocks/tiptap.d.ts +2 -0
- package/dist/agent/prompts/blocks/tiptap.d.ts.map +1 -0
- package/dist/agent/prompts/blocks/tiptap.js +100 -0
- package/dist/agent/prompts/index.d.ts +7 -0
- package/dist/agent/prompts/index.d.ts.map +1 -0
- package/dist/agent/prompts/index.js +6 -0
- package/dist/agent/prompts/repo_instructions.d.ts +3 -0
- package/dist/agent/prompts/repo_instructions.d.ts.map +1 -0
- package/dist/agent/prompts/repo_instructions.js +442 -0
- package/dist/agent/prompts/tool_descriptions.d.ts +4 -0
- package/dist/agent/prompts/tool_descriptions.d.ts.map +1 -0
- package/dist/agent/prompts/tool_descriptions.js +80 -0
- package/dist/agent/tools.d.ts +79 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +303 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +108 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +44 -0
- package/package.json +57 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import puppeteer from "puppeteer";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
/**
|
|
5
|
+
* Create a clickable terminal hyperlink using OSC 8 escape sequence
|
|
6
|
+
*/
|
|
7
|
+
export function createTerminalLink(url, text) {
|
|
8
|
+
// OSC 8 escape sequence for hyperlinks: \x1b]8;;URL\x1b\\TEXT\x1b]8;;\x1b\\
|
|
9
|
+
return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate a log message for file creation based on file type
|
|
13
|
+
*/
|
|
14
|
+
export function getFileCreationMessage(filePath, context) {
|
|
15
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
16
|
+
const fileName = path.basename(filePath);
|
|
17
|
+
const dirPath = path.dirname(filePath);
|
|
18
|
+
if (ext === ".html") {
|
|
19
|
+
// For HTML files, create a clickable link
|
|
20
|
+
if (context.projectId) {
|
|
21
|
+
// Convert file path to URL path (remove .html extension, use forward slashes)
|
|
22
|
+
const urlPath = filePath.replace(/\.html$/, "").replace(/\\/g, "/");
|
|
23
|
+
const url = `http://localhost:3000/${context.projectId}/${urlPath}`;
|
|
24
|
+
// Get display name without .html extension
|
|
25
|
+
const nameWithoutExt = fileName.replace(/\.html$/, "");
|
|
26
|
+
const displayName = dirPath === "." ? nameWithoutExt : filePath.replace(/\.html$/, "");
|
|
27
|
+
const clickableName = createTerminalLink(url, displayName);
|
|
28
|
+
return (chalk.green(`✓ Created ${clickableName} page`) +
|
|
29
|
+
`\n ${chalk.dim("🔄 Reload the page in your browser to see the updates.")}\n`);
|
|
30
|
+
}
|
|
31
|
+
const displayName = filePath.replace(/\.html$/, "");
|
|
32
|
+
return (chalk.green(`✓ Created: ${displayName}`) +
|
|
33
|
+
`\n ${chalk.dim("🔄 Reload the page in your browser to see the updates.")}\n`);
|
|
34
|
+
}
|
|
35
|
+
else if (ext === ".mdx") {
|
|
36
|
+
const displayPath = dirPath === "." ? fileName : filePath;
|
|
37
|
+
return chalk.dim(` → Creating component: ${displayPath}\n`);
|
|
38
|
+
}
|
|
39
|
+
else if (ext === ".json") {
|
|
40
|
+
const displayPath = dirPath === "." ? fileName : filePath;
|
|
41
|
+
return chalk.dim(` → Creating data structure: ${displayPath}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return chalk.green(`✓ Created: ${filePath}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the base destination path based on isUpdate flag
|
|
49
|
+
*/
|
|
50
|
+
export function getBaseDestinationPath(projectPath, isUpdate) {
|
|
51
|
+
if (isUpdate) {
|
|
52
|
+
return path.join(projectPath, ".davia", "proposed");
|
|
53
|
+
}
|
|
54
|
+
return path.join(projectPath, ".davia", "assets");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the assets path (for reading existing files)
|
|
58
|
+
*/
|
|
59
|
+
export function getAssetsPath(projectPath) {
|
|
60
|
+
return path.join(projectPath, ".davia", "assets");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper function to resolve file path using runtime context
|
|
64
|
+
* @param filePath - Relative file path
|
|
65
|
+
* @param context - Runtime context with projectPath and isUpdate
|
|
66
|
+
* @returns Absolute file path
|
|
67
|
+
* @throws Error if path validation fails
|
|
68
|
+
*/
|
|
69
|
+
export function resolveFilePath(filePath, context) {
|
|
70
|
+
// Validate that path doesn't start with /
|
|
71
|
+
if (filePath.startsWith("/")) {
|
|
72
|
+
throw new Error("Absolute paths with leading slash are not allowed. " +
|
|
73
|
+
`Use relative paths like 'page1/page2/file.html' instead of '${filePath}'`);
|
|
74
|
+
}
|
|
75
|
+
// Get base destination path based on isUpdate flag
|
|
76
|
+
const basePath = getBaseDestinationPath(context.projectPath, context.isUpdate);
|
|
77
|
+
// Join and normalize the path
|
|
78
|
+
const absolutePath = path.normalize(path.join(basePath, filePath));
|
|
79
|
+
const normalizedDestination = path.normalize(basePath);
|
|
80
|
+
// Security check: ensure the resolved path doesn't escape the destination directory
|
|
81
|
+
if (!absolutePath.startsWith(normalizedDestination)) {
|
|
82
|
+
throw new Error(`Path '${filePath}' attempts to escape the destination directory`);
|
|
83
|
+
}
|
|
84
|
+
return absolutePath;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse Mermaid diagram to Excalidraw using Puppeteer headless browser
|
|
88
|
+
* This is the same approach used by mermaid-cli for reliable rendering
|
|
89
|
+
* @param mermaidContent - Mermaid diagram definition
|
|
90
|
+
* @returns Excalidraw elements and files
|
|
91
|
+
*/
|
|
92
|
+
export async function parseMermaidWithPuppeteer(mermaidContent) {
|
|
93
|
+
const browser = await puppeteer.launch({
|
|
94
|
+
headless: true,
|
|
95
|
+
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
const page = await browser.newPage();
|
|
99
|
+
// Set up the page with the necessary libraries and parse
|
|
100
|
+
const result = await page.evaluate(
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
async (definition) => {
|
|
103
|
+
// Dynamically import the libraries in the browser context
|
|
104
|
+
const { parseMermaidToExcalidraw } = await import(
|
|
105
|
+
// @ts-expect-error - Runtime import in browser, not checked by TS
|
|
106
|
+
"https://cdn.jsdelivr.net/npm/@excalidraw/mermaid-to-excalidraw@1.1.3/+esm");
|
|
107
|
+
const { convertToExcalidrawElements } = await import(
|
|
108
|
+
// @ts-expect-error - Runtime import in browser, not checked by TS
|
|
109
|
+
"https://cdn.jsdelivr.net/npm/@excalidraw/excalidraw@0.18.0/+esm");
|
|
110
|
+
const { elements, files } = await parseMermaidToExcalidraw(definition);
|
|
111
|
+
const excalidrawElements = convertToExcalidrawElements(elements);
|
|
112
|
+
return { elements: excalidrawElements, files };
|
|
113
|
+
}, mermaidContent);
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
await browser.close();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Helper function to perform robust search and replace with validation
|
|
122
|
+
* @param content - Original file content
|
|
123
|
+
* @param oldString - String to search for
|
|
124
|
+
* @param newString - String to replace with
|
|
125
|
+
* @param replaceAll - Whether to replace all occurrences
|
|
126
|
+
* @returns Object with new content, success status, and error message
|
|
127
|
+
*/
|
|
128
|
+
export function robustSearchReplace(content, oldString, newString, replaceAll = false) {
|
|
129
|
+
// Check if old_string and new_string are the same
|
|
130
|
+
if (oldString === newString) {
|
|
131
|
+
return {
|
|
132
|
+
newContent: content,
|
|
133
|
+
success: false,
|
|
134
|
+
errorMessage: "old_string and new_string must be different",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Check if old_string exists in content
|
|
138
|
+
if (!content.includes(oldString)) {
|
|
139
|
+
return {
|
|
140
|
+
newContent: content,
|
|
141
|
+
success: false,
|
|
142
|
+
errorMessage: `The string to replace was not found in the file. Make sure old_string matches the file content exactly, including whitespace and indentation.`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// If not replacing all, check that old_string appears exactly once
|
|
146
|
+
if (!replaceAll) {
|
|
147
|
+
const occurrences = content.split(oldString).length - 1;
|
|
148
|
+
if (occurrences > 1) {
|
|
149
|
+
return {
|
|
150
|
+
newContent: content,
|
|
151
|
+
success: false,
|
|
152
|
+
errorMessage: `The string to replace appears ${occurrences} times in the file. Either provide more context to make old_string unique, or set replace_all to true.`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Perform the replacement
|
|
157
|
+
const newContent = replaceAll
|
|
158
|
+
? content.split(oldString).join(newString)
|
|
159
|
+
: content.replace(oldString, newString);
|
|
160
|
+
return {
|
|
161
|
+
newContent,
|
|
162
|
+
success: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively collect all file paths from a directory
|
|
3
|
+
* @param basePath - Base directory path to collect from
|
|
4
|
+
* @returns Array of relative paths (e.g., ["project-1.html", "project-1/overview.html"])
|
|
5
|
+
*/
|
|
6
|
+
export declare function collectPaths(basePath: string): Promise<string[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Convert a list of paths into a filesystem tree structure with full paths.
|
|
9
|
+
* HTML files are handled specially to maintain hierarchy by stripping .html extension
|
|
10
|
+
* for tree building, then re-adding it for display.
|
|
11
|
+
* @param paths - List of path strings (e.g., ["project-1.html", "project-1/overview.html"])
|
|
12
|
+
* @returns Formatted string representing the filesystem tree with full paths
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatTree(paths: string[]): string;
|
|
15
|
+
//# sourceMappingURL=tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/agent/helpers/tree.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmCtE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAqHlD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Recursively collect all file paths from a directory
|
|
5
|
+
* @param basePath - Base directory path to collect from
|
|
6
|
+
* @returns Array of relative paths (e.g., ["project-1.html", "project-1/overview.html"])
|
|
7
|
+
*/
|
|
8
|
+
export async function collectPaths(basePath) {
|
|
9
|
+
const paths = [];
|
|
10
|
+
async function traverseDirectory(currentPath, relativeBase) {
|
|
11
|
+
try {
|
|
12
|
+
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
15
|
+
const relativePath = path
|
|
16
|
+
.relative(relativeBase, fullPath)
|
|
17
|
+
.replace(/\\/g, "/");
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
await traverseDirectory(fullPath, relativeBase);
|
|
20
|
+
}
|
|
21
|
+
else if (entry.isFile()) {
|
|
22
|
+
paths.push(relativePath);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Skip directories we can't read
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
await traverseDirectory(basePath, basePath);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// If base path doesn't exist, return empty array
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return paths;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Convert a list of paths into a filesystem tree structure with full paths.
|
|
41
|
+
* HTML files are handled specially to maintain hierarchy by stripping .html extension
|
|
42
|
+
* for tree building, then re-adding it for display.
|
|
43
|
+
* @param paths - List of path strings (e.g., ["project-1.html", "project-1/overview.html"])
|
|
44
|
+
* @returns Formatted string representing the filesystem tree with full paths
|
|
45
|
+
*/
|
|
46
|
+
export function formatTree(paths) {
|
|
47
|
+
if (paths.length === 0) {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
// Separate HTML files from other files
|
|
51
|
+
const htmlPaths = [];
|
|
52
|
+
const otherPaths = [];
|
|
53
|
+
for (const filePath of paths) {
|
|
54
|
+
if (filePath.endsWith(".html")) {
|
|
55
|
+
htmlPaths.push(filePath);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
otherPaths.push(filePath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Build tree structure using a map
|
|
62
|
+
const tree = new Map();
|
|
63
|
+
// Process HTML files with special hierarchy handling
|
|
64
|
+
for (const filePath of htmlPaths.sort()) {
|
|
65
|
+
// Remove leading slash and .html extension for tree building
|
|
66
|
+
const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
67
|
+
if (!cleanPath) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// Strip .html extension for hierarchy
|
|
71
|
+
const pathWithoutExt = cleanPath.endsWith(".html")
|
|
72
|
+
? cleanPath.slice(0, -5)
|
|
73
|
+
: cleanPath;
|
|
74
|
+
const parts = pathWithoutExt.split("/");
|
|
75
|
+
if (parts.length === 1) {
|
|
76
|
+
// Root level file - add back .html extension for display
|
|
77
|
+
const part = parts[0];
|
|
78
|
+
if (part) {
|
|
79
|
+
const rootFiles = tree.get("") || [];
|
|
80
|
+
rootFiles.push(part + ".html");
|
|
81
|
+
tree.set("", rootFiles);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Nested structure - add back .html extension for display
|
|
86
|
+
const parent = parts.slice(0, -1).join("/");
|
|
87
|
+
const lastPart = parts[parts.length - 1];
|
|
88
|
+
if (lastPart) {
|
|
89
|
+
const childFiles = tree.get(parent) || [];
|
|
90
|
+
childFiles.push(lastPart + ".html");
|
|
91
|
+
tree.set(parent, childFiles);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Process non-HTML files (keep as-is)
|
|
96
|
+
for (const filePath of otherPaths.sort()) {
|
|
97
|
+
const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
98
|
+
if (!cleanPath) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const parts = cleanPath.split("/");
|
|
102
|
+
if (parts.length === 1) {
|
|
103
|
+
// Root level file
|
|
104
|
+
const part = parts[0];
|
|
105
|
+
if (part) {
|
|
106
|
+
const rootFiles = tree.get("") || [];
|
|
107
|
+
rootFiles.push(part);
|
|
108
|
+
tree.set("", rootFiles);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Nested structure
|
|
113
|
+
const parent = parts.slice(0, -1).join("/");
|
|
114
|
+
const lastPart = parts[parts.length - 1];
|
|
115
|
+
if (lastPart) {
|
|
116
|
+
const childFiles = tree.get(parent) || [];
|
|
117
|
+
childFiles.push(lastPart);
|
|
118
|
+
tree.set(parent, childFiles);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Format tree as string
|
|
123
|
+
function formatTreeRecursive(parentPath, indent = "") {
|
|
124
|
+
const children = tree.get(parentPath) || [];
|
|
125
|
+
if (children.length === 0) {
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
let result = "";
|
|
129
|
+
for (let i = 0; i < children.length; i++) {
|
|
130
|
+
const child = children[i];
|
|
131
|
+
if (!child)
|
|
132
|
+
continue;
|
|
133
|
+
const isLast = i === children.length - 1;
|
|
134
|
+
const prefix = isLast ? "└── " : "├── ";
|
|
135
|
+
result += `${indent}${prefix}${child}\n`;
|
|
136
|
+
// Recursively format children
|
|
137
|
+
const childPath = parentPath
|
|
138
|
+
? `${parentPath}/${child}`
|
|
139
|
+
: child.replace(/\.html$/, "");
|
|
140
|
+
const childTree = formatTreeRecursive(childPath, indent + (isLast ? " " : "│ "));
|
|
141
|
+
result += childTree;
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
return formatTreeRecursive("").trim();
|
|
146
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware that applies caching to AI and Tool messages after the model runs
|
|
3
|
+
* Ensures only the last AI message and last Tool message have cache control
|
|
4
|
+
*/
|
|
5
|
+
export declare const afterModelCachingMiddleware: import("langchain").AgentMiddleware<undefined, undefined, any>;
|
|
6
|
+
//# sourceMappingURL=after-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after-model.d.ts","sourceRoot":"","sources":["../../../src/agent/middlewares/after-model.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,eAAO,MAAM,2BAA2B,gEAetC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createMiddleware } from "langchain";
|
|
2
|
+
import { handleAIMessageCaching, handleToolMessageCaching, } from "../helpers/messages-caching-handler.js";
|
|
3
|
+
/**
|
|
4
|
+
* Middleware that applies caching to AI and Tool messages after the model runs
|
|
5
|
+
* Ensures only the last AI message and last Tool message have cache control
|
|
6
|
+
*/
|
|
7
|
+
export const afterModelCachingMiddleware = createMiddleware({
|
|
8
|
+
name: "AfterModelCaching",
|
|
9
|
+
afterModel: async (state, runtime) => {
|
|
10
|
+
// Get messages from state
|
|
11
|
+
const messages = state.messages || [];
|
|
12
|
+
// Handle AI message caching
|
|
13
|
+
handleAIMessageCaching(messages);
|
|
14
|
+
// Handle tool message caching
|
|
15
|
+
handleToolMessageCaching(messages);
|
|
16
|
+
// Return updated state with modified messages
|
|
17
|
+
return { messages };
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format repository content as markdown
|
|
3
|
+
* @param content - Dictionary of file paths to content
|
|
4
|
+
* @returns Formatted markdown string
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatRepositoryContent(content: Record<string, string>): string;
|
|
7
|
+
/**
|
|
8
|
+
* Middleware that initializes the agent with repository content
|
|
9
|
+
* Runs before the agent starts and injects repository files as formatted messages
|
|
10
|
+
*/
|
|
11
|
+
export declare const repositoryInitializationMiddleware: import("langchain").AgentMiddleware<undefined, import("zod").ZodObject<{
|
|
12
|
+
projectId: import("zod").ZodString;
|
|
13
|
+
projectPath: import("zod").ZodString;
|
|
14
|
+
isUpdate: import("zod").ZodBoolean;
|
|
15
|
+
modelName: import("zod").ZodString;
|
|
16
|
+
}, import("zod/v4/core").$strip>, any>;
|
|
17
|
+
//# sourceMappingURL=initialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initialization.d.ts","sourceRoot":"","sources":["../../../src/agent/middlewares/initialization.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CAYR;AAED;;;GAGG;AACH,eAAO,MAAM,kCAAkC;;;;;sCAsF7C,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createMiddleware, SystemMessage, HumanMessage, } from "langchain";
|
|
2
|
+
import { readRepositoryContent } from "../helpers/initialization.js";
|
|
3
|
+
import { STATIC_AGENT_INSTRUCT, DYNAMIC_AGENT_INSTRUCT, } from "../prompts/agent.js";
|
|
4
|
+
import { GIT_EXPLO_INSTRUCTIONS, HUMAN_MESSAGE, } from "../prompts/repo_instructions.js";
|
|
5
|
+
import { collectPaths, formatTree } from "../helpers/tree.js";
|
|
6
|
+
import { getAssetsPath } from "../helpers/tools.js";
|
|
7
|
+
import { contextSchema } from "../context.js";
|
|
8
|
+
/**
|
|
9
|
+
* Format repository content as markdown
|
|
10
|
+
* @param content - Dictionary of file paths to content
|
|
11
|
+
* @returns Formatted markdown string
|
|
12
|
+
*/
|
|
13
|
+
export function formatRepositoryContent(content) {
|
|
14
|
+
const files = Object.entries(content);
|
|
15
|
+
if (files.length === 0) {
|
|
16
|
+
return "No files found in repository.";
|
|
17
|
+
}
|
|
18
|
+
return files
|
|
19
|
+
.map(([path, fileContent]) => {
|
|
20
|
+
return `## File: ${path}\n\n${fileContent}\n`;
|
|
21
|
+
})
|
|
22
|
+
.join("\n");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Middleware that initializes the agent with repository content
|
|
26
|
+
* Runs before the agent starts and injects repository files as formatted messages
|
|
27
|
+
*/
|
|
28
|
+
export const repositoryInitializationMiddleware = createMiddleware({
|
|
29
|
+
name: "RepositoryInitialization",
|
|
30
|
+
contextSchema,
|
|
31
|
+
beforeAgent: async (state, runtime) => {
|
|
32
|
+
// Get context values
|
|
33
|
+
const { projectPath, isUpdate } = runtime.context;
|
|
34
|
+
// Get existing messages from state
|
|
35
|
+
const messages = state.messages || [];
|
|
36
|
+
// Read repository content
|
|
37
|
+
const repositoryContent = await readRepositoryContent(projectPath);
|
|
38
|
+
// Format as markdown
|
|
39
|
+
const formattedContent = formatRepositoryContent(repositoryContent);
|
|
40
|
+
// Create git exploration instructions with repository content
|
|
41
|
+
const gitExploInstructions = GIT_EXPLO_INSTRUCTIONS(formattedContent, isUpdate);
|
|
42
|
+
// Only insert if there's no existing system message
|
|
43
|
+
if (!messages.some((msg) => msg instanceof SystemMessage)) {
|
|
44
|
+
// Build system message content blocks
|
|
45
|
+
const contentBlocks = [
|
|
46
|
+
{
|
|
47
|
+
text: STATIC_AGENT_INSTRUCT,
|
|
48
|
+
type: "text",
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
// If isUpdate, add dynamic instruction with workspace tree
|
|
52
|
+
if (isUpdate) {
|
|
53
|
+
// Collect paths from assets folder
|
|
54
|
+
const assetsPath = getAssetsPath(projectPath);
|
|
55
|
+
const paths = await collectPaths(assetsPath);
|
|
56
|
+
const tree = formatTree(paths);
|
|
57
|
+
// Get current date and time
|
|
58
|
+
const currentDateTime = new Date().toISOString();
|
|
59
|
+
// Generate dynamic instruction
|
|
60
|
+
const dynamicInstruction = DYNAMIC_AGENT_INSTRUCT(currentDateTime, tree);
|
|
61
|
+
contentBlocks.push({
|
|
62
|
+
text: dynamicInstruction,
|
|
63
|
+
type: "text",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Add git exploration instructions
|
|
67
|
+
contentBlocks.push({
|
|
68
|
+
text: gitExploInstructions,
|
|
69
|
+
type: "text",
|
|
70
|
+
});
|
|
71
|
+
// Create a single SystemMessage with content blocks
|
|
72
|
+
const systemMessage = new SystemMessage({
|
|
73
|
+
content: contentBlocks,
|
|
74
|
+
});
|
|
75
|
+
// Insert at position 0
|
|
76
|
+
messages.unshift(systemMessage);
|
|
77
|
+
// Add human message after system message with cache control
|
|
78
|
+
const humanMessage = new HumanMessage({
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
text: HUMAN_MESSAGE,
|
|
82
|
+
type: "text",
|
|
83
|
+
cache_control: { type: "ephemeral", ttl: "5m" },
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
// Insert at position 1 (after system message)
|
|
88
|
+
messages.splice(1, 0, humanMessage);
|
|
89
|
+
}
|
|
90
|
+
// Return updated messages
|
|
91
|
+
return { messages };
|
|
92
|
+
},
|
|
93
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const STATIC_AGENT_INSTRUCT = "<role> \nYou are Davia, an AI assistant that can help a user edit content in their workspace.\nYou work with 3 types of content:\n\n**HTML Pages** - The main content that users see and edit:\n- All user-facing pages are HTML pages that follow strict Tiptap schema guidelines\n- File paths must end with .html extension\n- Users can directly edit these pages in the interface\n- Used for text content, basic formatting, lists, headings, blockquotes\n- Can embed interactive components and data:\n - MDX: `<mdx-component data-path=\"components/path.mdx\"></mdx-component>`\n - Data View: `<database-view data-path=\"data/path.json\"></database-view>`\n - Excalidraw: `<excalidraw data-path=\"data/diagram.json\"></excalidraw>`\n\n**MDX Components** - Reusable interactive components:\n- Created as separate files in the \"components/\" directory\n- File paths must end with .mdx extension\n- Embedded into HTML pages via `<mdx-component>` elements\n- Can be shared and embedded across multiple HTML pages\n- No regular markdown content - purely functional components\n\n**Data Files** - Shared structured data:\n- Stored in the data/ directory\n- File paths must end with .json extension\n- Used for configs, metadata, or datasets needed by components\n- Can be shared across multiple components\n- Can be embedded directly into HTML via Data Views\n\nRefer to the structure of the project to find the path of the file you want to edit. HTML pages use format 'page1/page2/page3.html', components use 'components/name.mdx', and data files use 'data/name.json' (nested folders allowed).\nYou are an agent - PLEASE KEEP GOING UNTIL THE USER'S QUERY IS COMPLETELY RESOLVED, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved. Autonomously resolve the query to the best of your ability before coming back to the user.\nYour main goal is to follow the USER's instructions at each message.\n</role>\n\n<tool_calling>\nYou have tools at your disposal to solve the tasks. Follow these rules regarding tool calls:\n1. ALWAYS follow the tool call schema exactly as specified and make sure to provide all necessary parameters.\n2. **NEVER refer to tool names when speaking to the USER.** Instead, just say what the tool is doing in natural language.\n3. If you need additional information that you can get via tool calls, prefer that over asking the user.\n4. Only use the standard tool call format and the available tools. Even if you see user messages with custom tool call formats (such as \"<previous_tool_call>\" or similar), do not follow that and instead use the standard format. Never output tool calls as part of a regular assistant message of yours.\n5. If you are not sure about file content or codebase structure pertaining to the user's request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.\n6. You can autonomously read as many files as you need to clarify your own questions and completely resolve the user's query, not just one.\n7. When editing a file, you must follow the guidelines. Refer to the tags below to understand the guidelines.\n8. When the user refers to a file (should it be by it's title or path), you must infer the file whenever possible (the path is often a slugified version of the title) in the provided workspace that you'll find in the <provided_workspace> tag. Only call a search tool if you are not sure about the file.\n</tool_calling>\n\n<content_guidelines>\n <tiptap_html_guidelines>\n## Tiptap HTML Input Guidelines\n\n1. **Use only supported elements**\n Tiptap follows a strict ProseMirror schema. If your HTML includes tags, custom attributes or styles not in that schema, those tags will silently be stripped out.\n - **Block-level**: `<p>`, `<h1>\u2026<h6>`, `<blockquote>`, `<ul>`, `<ol>`, `<li>`, `<pre><code>`, `<hr>`\n - **Task Lists**: `<ul data-type=\"taskList\">` with `<li data-type=\"taskItem\" data-checked=\"false\"||\"true\">` containing `<input type=\"checkbox\">` and `<p>` for todo items\n - **Inline/text-level**: `<strong>`, `<em>`, `<code>`, `<a>`, `<br>`\n - **MDX Components**: `<mdx-component data-path=\"components/component-name.mdx\"></mdx-component>` for embedding interactive components\n - **Data Views**: `<database-view data-path=\"data/path.json\"></database-view>` for displaying top-level array JSON directly in HTML\n - **Excalidraw Whiteboards**: `<excalidraw data-path=\"data/diagram.json\"></excalidraw>` for embedding interactive whiteboards\n Anything outside this list (like `<div>`, `<span>`, `<img>`) will be dropped unless the corresponding extension is added.\n\n2. **Well-formed HTML only**\n - Every tag must be properly opened and closed.\n - Lists must be correctly nested: e.g. `<ul><li>Item text</li></ul>`\n - Inline tags must be inside blocks: e.g. `<p>This is <strong>bold</strong> text.</p>`\n\n3. **No stray inline elements**\n Avoid standalone inline tags or text outside blocks.\n WRONG: `<strong>bold!</strong><p>Paragraph</p>`\n CORRECT: `<p><strong>bold!</strong></p><p>Paragraph</p>`\n\n4. **Creating Task Lists (Todo Lists)**\n To create interactive todo lists, use the task list structure:\n \n ```html\n <ul data-type=\"taskList\">\n <li data-checked=\"false\" data-type=\"taskItem\">\n <input type=\"checkbox\">\n <p>Task description here</p>\n </li>\n <li data-checked=\"true\" data-type=\"taskItem\">\n <input type=\"checkbox\" checked>\n <p>Completed task</p>\n </li>\n </ul>\n ```\n \n - Use `data-checked=\"false\"` for unchecked items\n - Use `data-checked=\"true\"` and `checked` attribute for completed items\n - Each task item contains an `<input type=\"checkbox\">` and a `<p>` with the task content\n\n5. **Embedding MDX Components**\n To embed interactive components in HTML pages, use the mdx-component element:\n \n ```html\n <mdx-component data-path=\"components/component-name.mdx\"></mdx-component>\n ```\n \n * HTML pages are for content structure only - no custom app logic\n * Interactive functionality and complex data handling should live within MDX components\n\n5a. **Embedding Data Views (Top-Level Arrays Only)**\n To directly display JSON data in HTML pages (without an MDX component), use the database-view element:\n \n ```html\n <database-view data-path=\"data/path.json\"></database-view>\n ```\n \n - Works only when the JSON file's root is a top-level array (table/list-like datasets)\n - For configs, single-value objects, or nested structures, use an MDX component instead\n\n6. **Spacing Multiple Components**\n When adding multiple `<mdx-component>`, `<database-view>`, or `<excalidraw>` blocks one after another, you MUST separate them with empty paragraphs to ensure proper editor behavior:\n \n ```html\n <mdx-component data-path=\"components/component1.mdx\"></mdx-component>\n <p></p>\n <database-view data-path=\"data/list-a.json\"></database-view>\n <p></p>\n <excalidraw data-path=\"data/diagram.json\"></excalidraw>\n ```\n \n This creates editable zones where users can position their cursor and add content\n\n7. **Commenting on the document**\n When the user asks for a comment on the document, you should use one of the valid blockquote tags to wrap the comment. \n You shouldn't place them inside HTML comments for they would be stripped out.\n\n### Sample Valid HTML\n```html\n<h1>Hello World</h1>\n<p>This is a <strong>bold</strong> paragraph.</p>\n<ul>\n <li>First item</li>\n <li>Second <em>item</em></li>\n</ul>\n<blockquote>A nice quote.</blockquote>\n<pre><code>console.log('hi');</code></pre>\n<hr />\n```\n\n### Example of Invalid HTML\n```html\n<div>A div tag</div>\n<span style=\"color:red;\">Red text</span>\n<p>Some <unknown>weird</unknown> tag.</p>\n```\n</tiptap_html_guidelines>\n <mdx_guidelines>\n\n# Main MDX Guidelines for Component Development\nMDX_GUIDELINES = f\"\"\"<mdx_guidelines>\n## MDX Component Guidelines\n\n### What are MDX Components?\nMDX components are reusable interactive React components that get embedded into HTML pages. They contain only functional, interactive elements - no regular markdown content.\n\n### When to Create MDX Components\n- When users need interactive widgets (forms, calculators, charts)\n- For dynamic data visualization or dashboards\n- When building custom functionality beyond basic HTML\n- For reusable interactive elements within pages\n\n### Component Development Best Practices\n\n**GOOD PRACTICE: START SIMPLE FIRST**\n- **Always begin with basic functionality** - avoid complex features initially\n- **Add complexity gradually** - enhance features incrementally after basic version works\n- **Resist over-engineering** - users can always request additional features later\n\n1. **Component Structure**\n - Create focused, single-purpose interactive components\n - Use only JSX/React components - NO markdown content\n - Export components that can be embedded in HTML pages\n - Ensure component paths match the data-path attribute exactly\n\n2. **Component Design**\n - Keep component logic simple and readable\n - Focus on interactive functionality only\n - Build incrementally - add features one at a time, not all at once unless requested by the user\n\n3. **State Management**\n - Import a JSON data source and bind it: `import sourceData from \"~/data/file.json\"`\n - Use `const { data, updateData } = useData(sourceData);` for persisted, shareable state\n - Use local component state for temporary interactions\n - Data is not scoped to a component or page; sharing is achieved by importing the same JSON file\n\n4. **Styling Approach**\n - Use Tailwind CSS classes from the approved safelist only\n - Leverage shadcn/ui components for consistent design\n - Keep inline styles minimal and purposeful\n - Maintain consistent design patterns across components\n\n### Example MDX Component Structure\n```mdx\nimport sales from \"~/data/sales.json\";\nimport { Button } from \"@/components/ui/button\";\n\nexport function SalesChart() {\n const { data, updateData } = useData(sales);\n \n // data is an array of sales records\n const salesData = data || [];\n \n return (\n <div className=\"p-4 border rounded\">\n <h3>Sales Records</h3>\n {salesData.map(record => (\n <div key={record.id} className=\"p-2 border-b\">\n <p>{record.month}: ${record.revenue}</p>\n </div>\n ))}\n </div>\n );\n}\n\n<SalesChart />\n```\n\n**Usage in HTML Page:**\n```html\n<h1>Dashboard</h1>\n<p>Welcome to our interactive dashboard.</p>\n<mdx-component data-path=\"components/sales-chart.mdx\"></mdx-component>\n<p></p>\n```\n\n<mdx_implementation>\n## Davia-Specific MDX Component Implementation\n\n### Critical Component Requirements\n\n1. **Component File Structure**\n - MDX components are created in the \"components/\" directory\n - File paths must match the data-path attribute exactly\n - Components are embedded in HTML pages via `<mdx-component data-path=\"components/name.mdx\"></mdx-component>`\n - Components can be shared across multiple HTML pages\n - NO markdown content - components contain only interactive functionality\n\n2. **Imports**\n - Data: `import dataSource from \"~/data/name.json\"`\n - UI: Import shadcn components from `@/components/ui/*`\n - Icons: Import icons from `lucide-react` (e.g., `import { ChevronDown, Plus, Search } from \"lucide-react\"`)\n - Utilities: `import { cn } from \"@/lib/utils\"`, `import { useIsMobile } from \"@/hooks/use-mobile\"`\n\n3. **React Usage**\n - React is globally available - use `React.useState`, `React.useEffect`, etc.\n - Always prefix React hooks and methods with `React.`\n\n4. **Component Data Persistence**\n - Bind component state to a specific data source: `const { data, updateData } = useData(dataSource);`\n - `dataSource` is the imported JSON reference (e.g., `import dataSource from \"~/data/name.json\"`)\n - Updates via `updateData(newData)` persist to the underlying JSON file and are shared wherever that file is used\n - **Avoid hardcoding data in component files** \u2014 define initial structure in the JSON file, and use `useData(importedRef)` to read/update it\n - Use the spread operator to preserve existing data when updating\n\n **Component Example:**\n ```mdx\n import counter from \"~/data/counter.json\";\n import { Button } from \"@/components/ui/button\";\n\n export function InteractiveCounter() {\n const { data, updateData } = useData(counter);\n const count = data.count || 0;\n \n const increment = () => {\n updateData({\n ...data,\n count: count + 1\n });\n };\n\n return (\n <div className=\"p-4 border rounded\">\n <p>Count: {count}</p>\n <Button onClick={increment}>Increment</Button>\n </div>\n );\n }\n\n <InteractiveCounter />\n ```\n\n5. **Tailwind CSS v4 (Safelist ONLY)**\n - The project uses Tailwind v4 with a strict safelist. Only the classes below are allowed.\n - Do NOT use any class names not present in this safelist (they will be stripped at build time).\n - Use `className` for styling as much as possible but if you need very specific styling, use inline styles (try to avoid if possible).\n\n **Color Usage Guidelines:**\n - **Text Colors**: Do NOT use text colors unless explicitly requested by users. Text colors are set globally through shadcn and nextjs.\n - **Background Colors**: When using background colors (not predefined globals like primary, muted, accent), always include `dark:` variants for light/dark mode compatibility.\n\n ```css\n /* Layout */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}{block,inline-block,inline,flex,inline-flex,grid,inline-grid,hidden}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}overflow-{auto,hidden,visible,scroll,x-auto,y-auto}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}position-{static,relative,absolute,fixed,sticky}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}{top,bottom,left,right,inset,inset-x,inset-y}-{0,auto}\");\n\n /* Flexbox & Grid */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}flex-{row,row-reverse,col,col-reverse}\", \"{,sm:,md:,lg:,xl:,2xl:}flex-wrap\", \"{,sm:,md:,lg:,xl:,2xl:}flex-nowrap\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}items-{start,end,center,baseline,stretch}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}justify-{start,end,center,between,around,evenly}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}gap-{0,1,2,3,4,5,6,8,10,12,16,20,24,32}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}grid-cols-{1,2,3,4,5,6,7,8,9,10,11,12}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}col-span-{1,2,3,4,5,6,7,8,9,10,11,12,full}\");\n\n /* Spacing */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}{p,m,px,py,pt,pr,pb,pl,mx,my,mt,mr,mb,ml}-{0,1,2,3,4,5,6,8,10,12,16,20,24,32,auto}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}space-{x,y}-{0,1,2,3,4,5,6,8,10,12,16,20,24,32}\");\n\n /* Sizing */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}{w,h}-{auto,full,screen,fit,min,max,'1/2','1/3','2/3','1/4','3/4','1/5','2/5','3/5','4/5'}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}max-w-{xs,sm,md,lg,xl,2xl,3xl,4xl,5xl,6xl,7xl,prose}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}{w,h}-{4,5,6,7,8,9,10,11,12}\");\n\n /* Typography */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}text-{xs,sm,base,lg,xl,2xl,3xl,4xl,5xl,6xl}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}font-{light,normal,medium,semibold,bold,extrabold}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}text-{left,center,right,justify}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}leading-{tight,snug,normal,relaxed,loose}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}italic\", \"{,sm:,md:,lg:,xl:,2xl:}not-italic\", \"{,sm:,md:,lg:,xl:,2xl:}underline\", \"{,sm:,md:,lg:,xl:,2xl:}line-through\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}list-{disc,decimal}\", \"{,sm:,md:,lg:,xl:,2xl:}list-inside\");\n\n /* Colors (semantic & grayscale) */\n @source inline(\"{,dark:,hover:,focus:,focus-visible:,active:}{bg,text,border,ring,fill,stroke}-{background,foreground,primary,primary-foreground,secondary,secondary-foreground,muted,muted-foreground,accent,accent-foreground,destructive,card,border,input,ring}\");\n @source inline(\"{,dark:,hover:,focus:,focus-visible:,active:}{bg,text,border,ring,fill,stroke}-{slate,gray,zinc,neutral,stone}-{50,{100..900..100},950}\");\n @source inline(\"{,dark:,hover:,focus:,focus-visible:,active:}{bg,text,border,ring,fill,stroke}-{red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,{100..900..100},950}\");\n @source inline(\"{,dark:,hover:,focus:,focus-visible:,active:}{bg,text,border,ring,fill,stroke}-{transparent,white,black}\");\n @source inline(\"ring-offset-{background,foreground,card,popover,white,black}\");\n\n /* Borders */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}rounded{,-t,-r,-b,-l,-tl,-tr,-br,-bl}-{sm,md,lg,xl,2xl,3xl,full}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}border{,-x,-y,-t,-r,-b,-l}-{0,1,2,4,8}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}divide-{x,y}-{0,1,2,4,8}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}ring-{0,1,2,4,8}\");\n\n /* Effects & Transitions */\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}shadow-{sm,md,lg,xl,2xl,inner,none}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}opacity-{0,25,50,75,100}\");\n @source inline(\"{,sm:,md:,lg:,xl:,2xl:}transition-all\", \"{,sm:,md:,lg:,xl:,2xl:}duration-{150,200,300,500,700}\");\n ```\n</mdx_implementation>\n\n<mdx_shadcn>\n## Shadcn Component Instructions\n\n### Best Practices\n1. **Composition**: Combine multiple components to create rich interfaces\n2. **Styling**: Use `className` prop for additional Tailwind CSS classes\n3. **State Management**: Manage component state within custom components\n\n### Forms\nUse the following imports for forms and validation. Import shadcn form components from `@/components/ui/form`.\n\n- **useForm** from react-hook-form - For form state management\n- **zodResolver** from @hookform/resolvers/zod - For form validation\n- **z** from zod - For schema validation\n\n```mdx\nimport { useForm } from \"react-hook-form\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { z } from \"zod\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from \"@/components/ui/form\";\n\nexport function ContactForm() {\n const formSchema = z.object({\n email: z.string().email(\"Please enter a valid email address\"),\n });\n\n const form = useForm({\n resolver: zodResolver(formSchema),\n defaultValues: {\n email: \"\",\n },\n });\n\n const onSubmit = (values) => {\n console.log(values);\n };\n\n return (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"email\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Email</FormLabel>\n <FormControl>\n <Input placeholder=\"Enter your email\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\">Submit</Button>\n </form>\n </Form>\n );\n}\n```\n\n### Charts\nRecharts v2 components are available for data visualization. Import them from `recharts` as shown below.\n**Important**: Remember to set a `min-h-[VALUE]` on the ChartContainer component. This is required for the chart to be responsive.\n**Colors**: Use direct hex, hsl, or oklch values in chartConfig instead of CSS variables. Default chart colors available:\n- **Chart 1**: `oklch(0.646 0.222 41.116)` (light) / `oklch(0.488 0.243 264.376)` (dark)\n- **Chart 2**: `oklch(0.6 0.118 184.704)` (light) / `oklch(0.696 0.17 162.48)` (dark)\n- **Chart 3**: `oklch(0.398 0.07 227.392)` (light) / `oklch(0.769 0.188 70.08)` (dark)\n- **Chart 4**: `oklch(0.828 0.189 84.429)` (light) / `oklch(0.627 0.265 303.9)` (dark)\n- **Chart 5**: `oklch(0.769 0.188 70.08)` (light) / `oklch(0.645 0.246 16.439)` (dark)\n\n```mdx\nimport { ChartContainer, ChartTooltip, ChartTooltipContent } from \"@/components/ui/chart\";\nimport { ResponsiveContainer, BarChart, Bar, CartesianGrid, XAxis, YAxis } from \"recharts\";\n\nexport function SalesChart() {\n const chartData = [\n { month: \"Jan\", sales: 4000, profit: 2400 },\n { month: \"Feb\", sales: 3000, profit: 1398 },\n { month: \"Mar\", sales: 2000, profit: 9800 },\n { month: \"Apr\", sales: 2780, profit: 3908 },\n { month: \"May\", sales: 1890, profit: 4800 },\n { month: \"Jun\", sales: 2390, profit: 3800 },\n ];\n\n const chartConfig = {\n sales: {\n label: \"Sales\",\n color: \"oklch(0.646 0.222 41.116)\",\n },\n profit: {\n label: \"Profit\", \n color: \"oklch(0.6 0.118 184.704)\",\n },\n };\n\n return (\n <ChartContainer config={chartConfig} className=\"min-h-[150px] w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"month\" />\n <YAxis />\n <ChartTooltip content={<ChartTooltipContent />} />\n <Bar dataKey=\"sales\" fill=\"var(--color-sales)\" />\n <Bar dataKey=\"profit\" fill=\"var(--color-profit)\" />\n </BarChart>\n </ResponsiveContainer>\n </ChartContainer>\n );\n}\n```\n\n### Toasts\nUse Sonner by importing `toast`:\n\n```mdx\nimport { Button } from \"@/components/ui/button\";\nimport { toast } from \"sonner\";\n\nexport function SimpleToast() {\n const handleClick = () => {\n toast('Event has been created');\n };\n\n return (\n <Button onClick={handleClick}>Show Toast</Button>\n );\n}\n```\n</mdx_shadcn>\n\n<mdx_custom_components>\n## Custom Component Instructions\n\n### Rules for Custom Components\n\n1. **Always Use Export**\n - All custom components must use `export function ComponentName()`\n - This makes them available throughout the MDX document\n\n2. **Keep Everything Inside**\n - ALL variables, functions, state, and logic must be declared inside the component\n - Never declare anything outside the component scope\n \n **WRONG:**\n ```mdx\n const initCounter = 4;\n export function CounterComponent() {\n const [count, setCount] = React.useState(initCounter);\n }\n ```\n \n **CORRECT:**\n ```mdx\n export function CounterComponent() {\n const initCounter = 4;\n const [count, setCount] = React.useState(initCounter);\n }\n ```\n\n3. **Component Placement**\n - ALL custom component definitions MUST be placed at the TOP of the document\n - Define components before any content or component usage\n - Never define components at the bottom or mixed within content\n - ALWAYS add a blank line between the last component and the beginning of MDX content\n \n **WRONG:**\n ```mdx\n export function InternEvents() {\n const events = [];\n return (<></>);\n }\n <InternEvents />\n ```\n \n **CORRECT:**\n ```mdx\n export function InternEvents() {\n const events = [];\n return (<></>);\n }\n\n <InternEvents />\n ```\n\n4. **Component Structure**\n - Use descriptive, PascalCase component names\n - Keep components self-contained with all logic inside\n - Components should be focused and single-purpose\n\n5. **String Quotes (IMPORTANT)**\n - Try to use double quotes `\"` for strings as much as possible, but if you need to use single quotes, use single quotes `'`\n - Triple quotes ```text``` will cause syntax errors\n \n **WRONG:**\n ```mdx\n const events = [\n { title: ```Meeting```, description: ```Team sync``` }\n ];\n ```\n \n **CORRECT:**\n ```mdx\n const events = [\n { title: \"Meeting\", description: \"Team sync\" }\n ];\n ```\n</mdx_custom_components>\n\n<available_packages>\nHere are the available secondary packages for you to use to build your components:\n- react-simple-maps@3.0.0 : ideal for lightweight, SVG-based map visualizations (choropleths, small geo overlays).\n(careful to set the geoUrl constant inside the component function)\n\n- usehooks-ts@3.1.1 : React hooks library, written in Typescript and easy to use. It provides a set of hooks that enables you to build your React applications faster.\nDo not hesitate to look at the documentation on the internet (use the web search tool) of the packages to see how to use them.\n</available_packages>\n</mdx_guidelines>\n <data_guidelines>\n## Data Guidelines\n\n### Purpose and Scope\nData files provide structured, persistent data that components can access and modify. Data can be shared across multiple components and HTML pages.\n\n### File Location and Naming\n- **Path Format**: `data/[name].json` (arbitrary names and nested folders allowed)\n- **Examples**: `data/projects.json`, `data/analytics/sales.json`\n- **Many-to-Many**: A single data file can be used by many components, and a component can use multiple data files\n- **Directory Structure**: Organize logically for reuse\n\n### Data File Structure\n**CRITICAL**: Data files must be valid JSON. For display via Data Views, the file's root MUST be a top-level array.\n\n**PREFERRED STRUCTURE**: Use top-level arrays whenever possible, similar to database tables.\n\n### Data Structure Guidelines\n\n1. **Top-Level Arrays (Preferred)**\n - Use when data feels like it belongs in a database table\n - Examples: `data/users.json`, `data/products.json`, `data/orders.json`\n - Structure: `[...]` - the JSON file should start with an array\n - Each array item represents a record/row\n\n2. **JSON Objects (Use Sparingly)**\n - Only for configuration, settings, or single-value data\n - Examples: `data/config.json` (app settings), `data/counter.json` (single counter value)\n - Avoid for data that could be tabular\n\n3. **Denormalized Data Structure (IMPORTANT)**\n - **Try to keep all related data in a single file** - Preferably do not split into multiple files with references\n - **Repeat information as needed** - denormalization is preferred over normalization\n - Avoid nested objects and arrays as property values - keep properties flat and primitive\n - Example (Good): \n```json\n [\n {\"order_id\": 1, \"user_name\": \"Alice\", \"user_email\": \"alice@example.com\", \"product\": \"Widget\", \"price\": 29.99},\n {\"order_id\": 2, \"user_name\": \"Alice\", \"user_email\": \"alice@example.com\", \"product\": \"Gadget\", \"price\": 49.99}\n ]\n```\n - Example (Bad - nested objects):\n```json\n [\n {\"order_id\": 1, \"user\": {\"name\": \"Alice\", \"email\": \"alice@example.com\"}, \"product\": {\"name\": \"Widget\", \"price\": 29.99}}\n ]\n```\n\n### Embedding Data Directly in HTML (Data View)\n\nYou can embed JSON directly in HTML using the Data View element without creating an MDX component:\n\n```html\n<database-view data-path=\"data/analytics/sales.json\"></database-view>\n```\n\n- Works only when the JSON file's root is a top-level array\n- Best for table/list-like datasets\n\n**Minimal JSON example for Data View**\n\n```json\n[\n { \"id\": 1, \"name\": \"Alice\" }\n]\n```\n\n### Best Practices\n\n1. **Data Organization**\n - Use meaningful property names\n - Include sensible default values\n - Prefer flat, tabular structures over nested ones\n\n2. **Content Guidelines**\n - Store component configuration, settings, and state\n - Include sample data for charts, tables, and lists\n - Define form defaults and validation parameters\n - Store user preferences and customization options\n - Create separate files for related but distinct data types\n\n### Common Mistakes to Avoid\n\n1. **Missing Defaults**: Always provide sensible default values in the data file\n2. **Hardcoding state in components**: Import JSON and use `useData(importedSource)` instead\n3. **Nested Properties**: Avoid arrays and objects as property values within objects\n4. **Over-normalization**: Prefer data repetition over splitting into multiple linked files\n\n**CRITICAL REMINDER**: Always maintain the exact JSON structure format shown above. The data must be a properly formatted JSON object that can be parsed and used by the component system.\n</data_guidelines>\n <excalidraw_guidelines>\n## Excalidraw Whiteboards (MANDATORY FOR VISUALS)\n\n### Purpose\nExcalidraw elements embed interactive whiteboards directly in HTML pages. Whiteboards can contain diagrams, visual workflows, sketches, notes, and other visual content. **Whiteboards are the primary visual tool** - use them liberally to explain concepts visually.\n\n### When to Create Whiteboards\n- **ALWAYS when user asks for a visual, chart, diagram, or flow**\n- **By default, be ultra-visual** - add whiteboards even if not explicitly requested\n- Use for: architecture diagrams, data flows, backend requests, frontend journeys, deployments, schemas, processes, workflows\n\n### Creating Excalidraw Data\n\n**Mermaid Auto-Conversion (MANDATORY - Use This)**\n1. **ALWAYS create mermaid files** in the `mermaids/` folder (which already exists in assets)\n2. **Mermaid workflow:**\n - Create a `.mmd` file in `mermaids/` folder (e.g., `mermaids/architecture-flow.mmd`)\n - **CRITICAL**: Write the mermaid syntax DIRECTLY in the file - DO NOT use code fences like ```mermaid```\n - Just write the raw mermaid diagram syntax (e.g., `graph TD`, `flowchart LR`, etc.)\n - The mermaid file will be automatically converted to an Excalidraw JSON file in `data/` folder\n - **IMPORTANT**: When embedding in HTML, always point to the JSON file in `data/`, NOT the mermaid file\n - Example: If mermaid is `mermaids/architecture-flow.mmd`, the converted JSON will be `data/architecture-flow.json`\n - Embed using: `<excalidraw data-path=\"data/architecture-flow.json\"></excalidraw>`\n\n**Direct JSON Creation (Only for Edge Cases)**\n- Only use if mermaid cannot represent what you need\n- Create a JSON file with an \"elements\" property containing ExcalidrawElement objects\n- Structure:\n```json\n{\n \"elements\": [\n // array of ExcalidrawElement objects\n ]\n}\n```\n\n### Embedding in HTML\n```html\n<excalidraw data-path=\"data/flow-example.json\"></excalidraw>\n```\n\n### Editing Excalidraw Data\n- **Small modifications** (colors, styling, minor text changes): Edit the JSON file directly in `data/`\n- **Structural changes** (adding/removing elements, changing layout): \n 1. Read the current JSON file from `data/`, understand its structure, and create/update the corresponding mermaid file in `mermaids/` with the same name (using `.mmd` extension) - replicate the structure as mermaid syntax with your edits applied (write mermaid syntax directly, no code fences)\n 2. The mermaid will be re-converted to JSON automatically\n\n### Text Formatting in Excalidraw\n- Do NOT use `<br>` for line breaks, use `\\n` instead\n- This applies when creating text content within Excalidraw elements\n\n</excalidraw_guidelines>\n</content_guidelines>\n\n<content_strategy>\n**How to handle user requests:**\n\n**CRITICAL FILE CREATION ORDER - MANDATORY:**\n- **NEVER create HTML files before their required components** - this will cause errors\n- **FOR EACH PAGE: Create data files and components FIRST, THEN create the HTML page**\n- **PROGRESSIVE PAGE-BY-PAGE APPROACH**: \n 1. For page 1: Create its JSON data files \u2192 Create its MDX components \u2192 THEN create the HTML page\n 2. For page 2: Create its JSON data files \u2192 Create its MDX components \u2192 THEN create the HTML page\n 3. Repeat for each subsequent page\n- **DO NOT create HTML pages first** - components must exist before being embedded in HTML\n- **DO NOT create all components for all pages, then all HTML files** - work page-by-page progressively\n\n**For MDX Components (CREATE THESE FIRST):**\n- Create MDX components when users request interactive functionality\n- **ALWAYS create the component FIRST before creating the HTML page** - this is non-negotiable\n- **MANDATORY CREATION ORDER**: Component file \u2192 HTML page (components are dependencies)\n- Components can be reused across multiple HTML pages\n- When creating multiple pages: For EACH page, create its required component files FIRST, then create that HTML page. Then move to the next page.\n- If you update an existing page: create/update ALL component files for that page FIRST, then update the HTML page to insert components\n- Use path format: \"components/component-name.mdx\" \n- Embed in HTML using: `<mdx-component data-path=\"components/component-name.mdx\"></mdx-component>`\n- MDX components contain ONLY: shadcn components, JSX expressions {}, custom components\n- NO regular markdown content in MDX components\n\n**For HTML Pages (CREATE THESE AFTER COMPONENTS):**\n- All user-facing content goes in HTML pages\n- **DO NOT create HTML files until their required components exist** - create components first\n- Use HTML for text content, basic formatting, lists, headings, blockquotes, etc.\n- Follow strict Tiptap schema guidelines\n- Start every HTML page with a top-level H1 heading: `<h1>[title of the page]</h1>` - **CRITICAL: The title MUST be `<h1>` and NEVER `<h2>`**\n- The file path should be EXACTLY equal to the H1 title in kebab case. Example: for `<h1>Plant Tracker</h1>`, use file path `plant-tracker.html`\n- When users need interactive functionality, create MDX components FIRST, then embed them in HTML\n\n\n**For Data Views (Top-Level Arrays Only):**\n1. Ensure the JSON file exists under `data/` and its root is a top-level array\n2. Edit/create the HTML page to embed it using: `<database-view data-path=\"data/path.json\"></database-view>`\n\n**For Excalidraw Whiteboards:**\n1. Create either a .mermaid file (RECOMMENDED, auto-converts to JSON) or direct JSON with \"elements\" property\n2. If using .mermaid, note the returned JSON path from the write operation\n3. Embed in HTML using: `<excalidraw data-path=\"data/diagram.json\"></excalidraw>`\n4. Whiteboards can contain diagrams, visual workflows, sketches, notes, and other visual content\n5. **When the user requests a diagram, create an Excalidraw whiteboard** - Excalidraw is a whiteboard tool that can contain diagrams\n\n** Workflow for interactive features (per page - follow this order exactly):**\n1. **FIRST**: Create any required JSON data files in \"data/\" directory for this page\n2. **SECOND**: Create the MDX component file(s) in \"components/\" directory with .mdx extension for this page\n3. Build the interactive functionality using React/shadcn components\n4. **Always persist component data by default** \u2014 import the JSON data you want to use and bind it with `const { data, updateData } = useData(dataset)`. Example: `import dataset from \"~/data/dataset.json\"`\n5. **ONLY AFTER steps 1-4 are complete**: Create the HTML page (with .html extension) to embed the component using `<mdx-component>` element\n6. Ensure the data-path matches the component file path\n7. Store shared JSON data under `data/` with any logical path/name (e.g., `data/analytics/sales.json`)\n8. **For multiple pages**: Complete steps 1-7 for the first page, then move to the next page and repeat\n</content_strategy>\n\n<communication>\nBe extremely concise in all communications. Use the fewest words possible to convey essential information.\nThis does not apply to the edits you make, the conciseness only applies to your verbal explanations or commentary.\nPLEASE KEEP YOUR VERBAL RESPONSE OR COMMENTARY TO THE USER UNDER 50 WORDS.\n\nFor example: when you're editing a file, you can say: \"I'll edit the file 'page1/page2/page3'\"\nwhen you're done editing, you can say: \"I've edited the file 'page1/page2/page3' to add a new section about the user's preferences.\"\n</communication>\n\n<file_handling_instructions>\n## VERY IMPORTANT: these rules ONLY apply to html files.\n\n### File Creation and Editing Guidelines for Hierarchical File System\nThis guideline defines the rules and best practices for how you should create and edit files in a hierarchical file system where folders are represented as files, and each file can have subfiles. This is critical to maintain data integrity, prevent race conditions, and optimize compute.\n\n1. Hierarchical Structure Principles\n- Folders are represented as files in the system\n- Subfiles are referenced as parent-file/sub-file in the database, where the parent file's ID serves as the parent reference.\n- A parent file must always exist before any of its subfiles can be created\n- This applies even if the parent file is initially empty\n\n<Example>\nfile1 must exist before file1/subfile1 or file1/subfile2 are created.\nIf file1 does not exist, it should be created first, even as an empty placeholder.\n</Example>\n\n2. File Creation Strategy\n- **Root-Proximal Priority**: Files closest to the root must be created first\n- **Depth-Based Sequential Creation**: Creation should proceed level by level (Level 0 \u2192 Level 1 \u2192 Level 2 \u2192 ...)\n- **Sequential Operations**: All file creations and edits must be performed sequentially - parallel operations are forbidden to prevent race conditions \n\n<Example> \nNO: Creating file1 and file1/subfile1 in parallel. \nNO: Editing file1 and file1/subfile1 in parallel. \nNO: Creating file1/subfile1 and file1/subfile2 in parallel. \nYES: Create file1, then create file1/subfile1, then create file1/subfile2. \n</Example>\n</file_handling_instructions>\n";
|
|
2
|
+
/**
|
|
3
|
+
* Generate dynamic agent instruction with provided workspace
|
|
4
|
+
* @param currentDateTime - Current date and time string
|
|
5
|
+
* @param elements - Formatted filesystem tree string
|
|
6
|
+
* @returns Formatted instruction string
|
|
7
|
+
*/
|
|
8
|
+
export declare function DYNAMIC_AGENT_INSTRUCT(currentDateTime: string, elements: string): string;
|
|
9
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/agent/prompts/agent.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,k7pCAuHjC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,GACf,MAAM,CAmBR"}
|