@vedangiitb/qwintly-core 1.3.7 → 1.3.8

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.
Files changed (37) hide show
  1. package/dist/ai/prompts/codegen.prompt.d.ts.map +1 -1
  2. package/dist/ai/prompts/codegen.prompt.js +37 -39
  3. package/dist/ai/prompts/codegen.prompt.js.map +1 -1
  4. package/dist/ai/prompts/examples/planner.examples.d.ts.map +1 -1
  5. package/dist/ai/prompts/examples/planner.examples.js +6 -1
  6. package/dist/ai/prompts/examples/planner.examples.js.map +1 -1
  7. package/dist/ai/prompts/helpers/promptParts.helper.d.ts +1 -3
  8. package/dist/ai/prompts/helpers/promptParts.helper.d.ts.map +1 -1
  9. package/dist/ai/prompts/helpers/promptParts.helper.js +9 -18
  10. package/dist/ai/prompts/helpers/promptParts.helper.js.map +1 -1
  11. package/dist/ai/prompts/planner.prompt.d.ts.map +1 -1
  12. package/dist/ai/prompts/planner.prompt.js +32 -36
  13. package/dist/ai/prompts/planner.prompt.js.map +1 -1
  14. package/dist/ai/prompts/validator.prompt.d.ts.map +1 -1
  15. package/dist/ai/prompts/validator.prompt.js +38 -39
  16. package/dist/ai/prompts/validator.prompt.js.map +1 -1
  17. package/dist/ai/tools/implementations/insertElement.impl.d.ts.map +1 -1
  18. package/dist/ai/tools/implementations/insertElement.impl.js +1 -1
  19. package/dist/ai/tools/implementations/insertElement.impl.js.map +1 -1
  20. package/dist/ai/tools/schemas/insertElement.schema.d.ts.map +1 -1
  21. package/dist/ai/tools/schemas/insertElement.schema.js +6 -6
  22. package/dist/ai/tools/schemas/insertElement.schema.js.map +1 -1
  23. package/dist/image/unsplash.service.d.ts.map +1 -1
  24. package/dist/image/unsplash.service.js +1 -0
  25. package/dist/image/unsplash.service.js.map +1 -1
  26. package/dist/indexer/data/configs.constants.d.ts +21 -28
  27. package/dist/indexer/data/configs.constants.d.ts.map +1 -1
  28. package/dist/indexer/data/configs.constants.js +34 -45
  29. package/dist/indexer/data/configs.constants.js.map +1 -1
  30. package/dist/types/public.d.ts +0 -1
  31. package/dist/types/public.d.ts.map +1 -1
  32. package/dist/types/public.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/types/index/conventions.types.d.ts +0 -40
  35. package/dist/types/index/conventions.types.d.ts.map +0 -1
  36. package/dist/types/index/conventions.types.js +0 -2
  37. package/dist/types/index/conventions.types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAY,MAAM,uBAAuB,CAAC;AAQjF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,GAAG,CAAC;IACV,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,uBAAuB,WA8E5D,CAAC"}
1
+ {"version":3,"file":"codegen.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,GAAG,CAAC;IACV,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,uBAAuB,WAoE5D,CAAC"}
@@ -2,51 +2,49 @@ import { codegenExamples } from "./examples/codegen.examples.js";
2
2
  import { jsonBlock, mdSection, projectStateNote, } from "./helpers/promptParts.helper.js";
3
3
  export const codegenPrompt = (params) => {
4
4
  const { task, codegenIndex, collectedContext, isNewProject } = params;
5
- const intialPrompt = `You are a senior software engineer responsible for implementing ONE coding task precisely and safely within an existing codebase.
6
- ${projectStateNote(isNewProject, "codegen")}
7
- `;
8
- const context = mdSection("Context (Authoritative)", [
9
- jsonBlock("Project Context (User preferences etc.)", collectedContext ?? {}),
10
- ].join("\n"));
11
- const projectConfiguration = mdSection("Project Configuration", [
12
- jsonBlock("FRAMEWORK CONFIG", codegenIndex.projectConfigs.frameworkConfig),
13
- jsonBlock("RUNTIME CONFIG", codegenIndex.projectConfigs.runtimeConfig),
14
- jsonBlock("RENDERING CONFIGURATION", codegenIndex.projectConfigs.renderingConfig),
15
- ].join("\n"));
16
- const toolsInfo = mdSection("Tool Usage", `
17
- You are provided access to the following tools and use them to implement coding tasks.
18
-
19
- read_file: Use when you want to read a file from the codebase.
5
+ const system = `
6
+ You are a senior software engineer implementing tasks in an existing codebase.
20
7
 
21
- list_dir: Use when you want to list the directory structure of a given path.
8
+ Rules:
9
+ - Implement ONLY the requested task.
10
+ - Prefer incremental edits over rewrites.
11
+ - Be concise and deterministic.
12
+ - Do not output code directly; use tools.
22
13
 
23
- create_new_route: Use when you want to create a new route. It will create a new route with a page.tsx and pageConfig.json (initial contents) file.
24
-
25
- insert_element: Use when you want to insert a new element in the config
26
-
27
- delete_element: Use when you want to delete an element from the config.
14
+ ${projectStateNote(isNewProject, "codegen")}
15
+ `.trim();
16
+ const taskInfo = mdSection("Task to implement", jsonBlock("task", task ?? null));
17
+ const toolsInfo = mdSection("Tools", `
18
+ Available tools:
28
19
 
29
- update_classname: Use when you want to update the className of an element.
30
-
31
- update_props: Use when you want to update the props of an element.
20
+ - read_file: Read file
21
+ - list_dir: List directory
22
+ - create_new_route: Create route with page.tsx + pageConfig.json
23
+ - insert_element: Insert element tree
24
+ - delete_element: Delete element
25
+ - update_classname: Update className
26
+ - update_props: Update props
27
+ - submit_codegen_done: Finish task
32
28
 
33
- submit_codegen_done: Use when you are done with the task and want to submit the codegen to the backend for validation.
34
-
35
- Important things to note:
36
- 1. If you want to insert an element to a route, use only 1 insert_element call with all its children. DO NOT use multiple insert_element calls for inserting children for an element.
37
- 2. If a route doesn't exists, please create it using the create_new_route tool.
38
- 3. When you are adding an image, just give the alt, which should be clear description of the image. The src of the image will be taken care by us.
39
- 4. For icons use only lucide-react icons.
40
- `);
41
- const taskInfo = mdSection("Task (Authoritative)", jsonBlock("TASK (You need to implement)", task ?? null));
42
- const examples = codegenExamples;
29
+ Rules:
30
+ - One insert_element per tree (include children inline) unless depth blocks it.
31
+ - Create missing routes with create_new_route.
32
+ - image src auto-generated from alt
33
+ - lucide-react icons only
34
+ `.trim());
35
+ const projectConfiguration = mdSection("Project Config", [
36
+ jsonBlock("framework", codegenIndex.projectConfigs.frameworkConfig),
37
+ jsonBlock("runtime", codegenIndex.projectConfigs.runtimeConfig),
38
+ jsonBlock("rendering", codegenIndex.projectConfigs.renderingConfig),
39
+ ].join("\n"));
40
+ const context = mdSection("Relevant Context", jsonBlock("context", collectedContext ?? {}));
43
41
  const sections = [
44
- intialPrompt,
45
- context,
46
- projectConfiguration,
47
- toolsInfo,
48
- examples,
42
+ system,
49
43
  taskInfo,
44
+ toolsInfo,
45
+ projectConfiguration,
46
+ context,
47
+ codegenExamples,
50
48
  ];
51
49
  return sections.join("\n\n---\n\n");
52
50
  };
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,gBAAgB,GACjB,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA+B,EAAE,EAAE;IAC/D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEtE,MAAM,YAAY,GAAG;EACrB,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;KACtC,CAAC;IAEJ,MAAM,OAAO,GAAG,SAAS,CACvB,yBAAyB,EACzB;QACE,SAAS,CACP,yCAAyC,EACzC,gBAAgB,IAAI,EAAE,CACvB;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,oBAAoB,GAAG,SAAS,CACpC,uBAAuB,EACvB;QACE,SAAS,CACP,kBAAkB,EAClB,YAAY,CAAC,cAAc,CAAC,eAAe,CAC5C;QACD,SAAS,CAAC,gBAAgB,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QACtE,SAAS,CACP,yBAAyB,EACzB,YAAY,CAAC,cAAc,CAAC,eAAe,CAC5C;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,YAAY,EAEZ;;;;;;;;;;;;;;;;;;;;;;;;GAwBD,CACA,CAAC;IAEF,MAAM,QAAQ,GAAG,SAAS,CACxB,sBAAsB,EACtB,SAAS,CAAC,8BAA8B,EAAE,IAAI,IAAI,IAAI,CAAC,CACxD,CAAC;IAEF,MAAM,QAAQ,GAAG,eAAe,CAAC;IAEjC,MAAM,QAAQ,GAAG;QACf,YAAY;QACZ,OAAO;QACP,oBAAoB;QACpB,SAAS;QACT,QAAQ;QACR,QAAQ;KACT,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { CodegenIndex, CollectedContext, PlanTask } from \"../../types/public.js\";\r\nimport { codegenExamples } from \"./examples/codegen.examples.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n projectStateNote,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type CodegenNodePromptParams = {\r\n task: any;\r\n codegenIndex: CodegenIndex;\r\n collectedContext: CollectedContext;\r\n isNewProject: boolean;\r\n};\r\n\r\nexport const codegenPrompt = (params: CodegenNodePromptParams) => {\r\n const { task, codegenIndex, collectedContext, isNewProject } = params;\r\n\r\n const intialPrompt = `You are a senior software engineer responsible for implementing ONE coding task precisely and safely within an existing codebase.\r\n${projectStateNote(isNewProject, \"codegen\")}\r\n `;\r\n\r\n const context = mdSection(\r\n \"Context (Authoritative)\",\r\n [\r\n jsonBlock(\r\n \"Project Context (User preferences etc.)\",\r\n collectedContext ?? {},\r\n ),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Configuration\",\r\n [\r\n jsonBlock(\r\n \"FRAMEWORK CONFIG\",\r\n codegenIndex.projectConfigs.frameworkConfig,\r\n ),\r\n jsonBlock(\"RUNTIME CONFIG\", codegenIndex.projectConfigs.runtimeConfig),\r\n jsonBlock(\r\n \"RENDERING CONFIGURATION\",\r\n codegenIndex.projectConfigs.renderingConfig,\r\n ),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tool Usage\",\r\n\r\n `\r\n You are provided access to the following tools and use them to implement coding tasks.\r\n\r\n read_file: Use when you want to read a file from the codebase.\r\n\r\n list_dir: Use when you want to list the directory structure of a given path.\r\n\r\n create_new_route: Use when you want to create a new route. It will create a new route with a page.tsx and pageConfig.json (initial contents) file.\r\n \r\n insert_element: Use when you want to insert a new element in the config\r\n \r\n delete_element: Use when you want to delete an element from the config.\r\n\r\n update_classname: Use when you want to update the className of an element.\r\n \r\n update_props: Use when you want to update the props of an element.\r\n\r\n submit_codegen_done: Use when you are done with the task and want to submit the codegen to the backend for validation.\r\n\r\n Important things to note:\r\n 1. If you want to insert an element to a route, use only 1 insert_element call with all its children. DO NOT use multiple insert_element calls for inserting children for an element.\r\n 2. If a route doesn't exists, please create it using the create_new_route tool.\r\n 3. When you are adding an image, just give the alt, which should be clear description of the image. The src of the image will be taken care by us.\r\n 4. For icons use only lucide-react icons.\r\n `,\r\n );\r\n\r\n const taskInfo = mdSection(\r\n \"Task (Authoritative)\",\r\n jsonBlock(\"TASK (You need to implement)\", task ?? null),\r\n );\r\n\r\n const examples = codegenExamples;\r\n\r\n const sections = [\r\n intialPrompt,\r\n context,\r\n projectConfiguration,\r\n toolsInfo,\r\n examples,\r\n taskInfo,\r\n ];\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
1
+ {"version":3,"file":"codegen.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,gBAAgB,GACjB,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA+B,EAAE,EAAE;IAC/D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEtE,MAAM,MAAM,GAAG;;;;;;;;;MASX,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;GAC5C,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,QAAQ,GAAG,SAAS,CACxB,mBAAmB,EACnB,SAAS,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EACP;;;;;;;;;;;;;;;;;KAiBC,CAAC,IAAI,EAAE,CACT,CAAC;IAEF,MAAM,oBAAoB,GAAG,SAAS,CACpC,gBAAgB,EAChB;QACE,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;QAEnE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QAE/D,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;KACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,OAAO,GAAG,SAAS,CACvB,kBAAkB,EAClB,SAAS,CAAC,SAAS,EAAE,gBAAgB,IAAI,EAAE,CAAC,CAC7C,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,MAAM;QACN,QAAQ;QACR,SAAS;QACT,oBAAoB;QACpB,OAAO;QACP,eAAe;KAChB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { CodegenIndex, CollectedContext } from \"../../types/public.js\";\r\nimport { codegenExamples } from \"./examples/codegen.examples.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n projectStateNote,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type CodegenNodePromptParams = {\r\n task: any;\r\n codegenIndex: CodegenIndex;\r\n collectedContext: CollectedContext;\r\n isNewProject: boolean;\r\n};\r\n\r\nexport const codegenPrompt = (params: CodegenNodePromptParams) => {\r\n const { task, codegenIndex, collectedContext, isNewProject } = params;\r\n\r\n const system = `\r\n You are a senior software engineer implementing tasks in an existing codebase.\r\n\r\n Rules:\r\n - Implement ONLY the requested task.\r\n - Prefer incremental edits over rewrites.\r\n - Be concise and deterministic.\r\n - Do not output code directly; use tools.\r\n\r\n ${projectStateNote(isNewProject, \"codegen\")}\r\n `.trim();\r\n\r\n const taskInfo = mdSection(\r\n \"Task to implement\",\r\n jsonBlock(\"task\", task ?? null),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n `\r\n Available tools:\r\n\r\n - read_file: Read file\r\n - list_dir: List directory\r\n - create_new_route: Create route with page.tsx + pageConfig.json\r\n - insert_element: Insert element tree\r\n - delete_element: Delete element\r\n - update_classname: Update className\r\n - update_props: Update props\r\n - submit_codegen_done: Finish task\r\n\r\n Rules:\r\n - One insert_element per tree (include children inline) unless depth blocks it.\r\n - Create missing routes with create_new_route.\r\n - image src auto-generated from alt\r\n - lucide-react icons only\r\n `.trim(),\r\n );\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Config\",\r\n [\r\n jsonBlock(\"framework\", codegenIndex.projectConfigs.frameworkConfig),\r\n\r\n jsonBlock(\"runtime\", codegenIndex.projectConfigs.runtimeConfig),\r\n\r\n jsonBlock(\"rendering\", codegenIndex.projectConfigs.renderingConfig),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const context = mdSection(\r\n \"Relevant Context\",\r\n jsonBlock(\"context\", collectedContext ?? {}),\r\n );\r\n\r\n const sections = [\r\n system,\r\n taskInfo,\r\n toolsInfo,\r\n projectConfiguration,\r\n context,\r\n codegenExamples,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"planner.examples.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompts/examples/planner.examples.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,eAAe,QAAsB,CAAC"}
1
+ {"version":3,"file":"planner.examples.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompts/examples/planner.examples.ts"],"names":[],"mappings":"AAqCA,eAAO,MAAM,eAAe,QAAsB,CAAC"}
@@ -13,12 +13,16 @@ Tool call:
13
13
  "targets": ["app/pricing/page.tsx", "app/pricing/pageConfig.json"]
14
14
  },
15
15
  {
16
- "description": "Update app/pricing/pageConfig.json to add a hero section with a title, subtitle, and two buttons (Primary: 'Start free trial' routes to /signup, Secondary: 'View docs' opens an external link in a new tab). Ensure all elements have ids and use Tailwind className strings only.",
16
+ "description": "Update app/pricing/pageConfig.json to add a hero section with a title, subtitle, and two buttons (Primary: 'Start free trial' routes to /signup, Secondary: 'View docs' opens an external link in a new tab). Add a hero image, a person sitting on a laptop in a bright office, and a quote. Ensure all elements have ids and use Tailwind className strings only.",
17
17
  "targets": ["app/pricing/pageConfig.json"]
18
18
  },
19
19
  {
20
20
  "description": "Add a 3-tier pricing cards section (Starter/Pro/Enterprise) in app/pricing/pageConfig.json with consistent spacing, responsive layout, and clear feature bullet lists. Use lucide-react icons for checkmarks and keep the JSON tree minimal and readable.",
21
21
  "targets": ["app/pricing/pageConfig.json"]
22
+ },
23
+ {
24
+ "description": "Create an items section for cakes. Include images of cakes",
25
+ "targets": ["app/items/pageConfig.json"]
22
26
  }
23
27
  ]
24
28
  }
@@ -26,6 +30,7 @@ Tool call:
26
30
 
27
31
  Notes:
28
32
  - Each task must be atomic and ordered.
33
+ - You can ask to include images whereever needed in the task description. Also tell what the image should be.
29
34
  - \`description\` must NOT include code blocks; reference exact paths and expected end state.
30
35
  - \`targets\` must be workspace-relative paths that will be modified or referenced.`,
31
36
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"planner.examples.js","sourceRoot":"","sources":["../../../../src/ai/prompts/examples/planner.examples.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG;IACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;oFA4BkF;CACnF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC","sourcesContent":["const examples = [\n `## Examples\n\n### Example: \\`submit_planner_tasks\\` (final response format)\nGoal: Return an ordered, atomic task list for the codegen agent.\n\nTool call:\n\\`\\`\\`json\n{\n \"planner_tasks\": [\n {\n \"description\": \"Create the /pricing route using create_new_route if it does not exist, and ensure app/pricing/page.tsx imports and renders the pageConfig.json elements via the standard renderer pattern used in this repo.\",\n \"targets\": [\"app/pricing/page.tsx\", \"app/pricing/pageConfig.json\"]\n },\n {\n \"description\": \"Update app/pricing/pageConfig.json to add a hero section with a title, subtitle, and two buttons (Primary: 'Start free trial' routes to /signup, Secondary: 'View docs' opens an external link in a new tab). Ensure all elements have ids and use Tailwind className strings only.\",\n \"targets\": [\"app/pricing/pageConfig.json\"]\n },\n {\n \"description\": \"Add a 3-tier pricing cards section (Starter/Pro/Enterprise) in app/pricing/pageConfig.json with consistent spacing, responsive layout, and clear feature bullet lists. Use lucide-react icons for checkmarks and keep the JSON tree minimal and readable.\",\n \"targets\": [\"app/pricing/pageConfig.json\"]\n }\n ]\n}\n\\`\\`\\`\n\nNotes:\n- Each task must be atomic and ordered.\n- \\`description\\` must NOT include code blocks; reference exact paths and expected end state.\n- \\`targets\\` must be workspace-relative paths that will be modified or referenced.`,\n];\n\nexport const plannerExamples = examples.join(\"\\n\");\n"]}
1
+ {"version":3,"file":"planner.examples.js","sourceRoot":"","sources":["../../../../src/ai/prompts/examples/planner.examples.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG;IACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oFAiCkF;CACnF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC","sourcesContent":["const examples = [\n `## Examples\n\n### Example: \\`submit_planner_tasks\\` (final response format)\nGoal: Return an ordered, atomic task list for the codegen agent.\n\nTool call:\n\\`\\`\\`json\n{\n \"planner_tasks\": [\n {\n \"description\": \"Create the /pricing route using create_new_route if it does not exist, and ensure app/pricing/page.tsx imports and renders the pageConfig.json elements via the standard renderer pattern used in this repo.\",\n \"targets\": [\"app/pricing/page.tsx\", \"app/pricing/pageConfig.json\"]\n },\n {\n \"description\": \"Update app/pricing/pageConfig.json to add a hero section with a title, subtitle, and two buttons (Primary: 'Start free trial' routes to /signup, Secondary: 'View docs' opens an external link in a new tab). Add a hero image, a person sitting on a laptop in a bright office, and a quote. Ensure all elements have ids and use Tailwind className strings only.\",\n \"targets\": [\"app/pricing/pageConfig.json\"]\n },\n {\n \"description\": \"Add a 3-tier pricing cards section (Starter/Pro/Enterprise) in app/pricing/pageConfig.json with consistent spacing, responsive layout, and clear feature bullet lists. Use lucide-react icons for checkmarks and keep the JSON tree minimal and readable.\",\n \"targets\": [\"app/pricing/pageConfig.json\"]\n },\n {\n \"description\": \"Create an items section for cakes. Include images of cakes\",\n \"targets\": [\"app/items/pageConfig.json\"]\n }\n ]\n}\n\\`\\`\\`\n\nNotes:\n- Each task must be atomic and ordered.\n- You can ask to include images whereever needed in the task description. Also tell what the image should be.\n- \\`description\\` must NOT include code blocks; reference exact paths and expected end state.\n- \\`targets\\` must be workspace-relative paths that will be modified or referenced.`,\n];\n\nexport const plannerExamples = examples.join(\"\\n\");\n"]}
@@ -1,8 +1,6 @@
1
1
  export type PromptRole = "planner" | "codegen" | "validator";
2
- export declare const mdDivider: () => string;
3
2
  export declare const mdSection: (title: string, body: string) => string;
4
3
  export declare const jsonBlock: (label: string, value: unknown) => string;
5
- export declare const projectStateNote: (isNewProject: boolean, role: PromptRole) => "The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify it per the PM plan; ensure there are no traces of boilerplate in the final project." | "The project has already gone through some stages of modification. Create tasks only for the latest PM recommendations and avoid rework." | "The project is currently a boilerplate. Implement the task cleanly while removing unnecessary boilerplate patterns." | "The project has existing modifications. Implement the task incrementally without breaking existing architecture.";
4
+ export declare const projectStateNote: (isNewProject: boolean, role: PromptRole) => "The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify project according to PM plan and context; remove boilerplate traces." | "Plan only latest PM changes; avoid rework" | "The project is currently a boilerplate. Implement task cleanly while removing boilerplate patterns." | "Implement task incrementally without breaking existing architecture.";
6
5
  export declare const renderPlannerTaskFormatSection: () => string;
7
- export declare const plannerObjectives: (target: PromptRole) => string;
8
6
  //# sourceMappingURL=promptParts.helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"promptParts.helper.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompts/helpers/promptParts.helper.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7D,eAAO,MAAM,SAAS,cAAkB,CAAC;AAEzC,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAGpD,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,OAAO,OAAO,WACG,CAAC;AAE3D,eAAO,MAAM,gBAAgB,GAAI,cAAc,OAAO,EAAE,MAAM,UAAU,ykBAUvE,CAAC;AAEF,eAAO,MAAM,8BAA8B,cAexC,CAAC;AAEJ,eAAO,MAAM,iBAAiB,GAAI,QAAQ,UAAU,WAWjD,CAAC"}
1
+ {"version":3,"file":"promptParts.helper.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompts/helpers/promptParts.helper.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7D,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAGpD,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,OAAO,OAAO,WACR,CAAC;AAEhD,eAAO,MAAM,gBAAgB,GAAI,cAAc,OAAO,EAAE,MAAM,UAAU,gaAUvE,CAAC;AAEF,eAAO,MAAM,8BAA8B,cAexC,CAAC"}
@@ -1,37 +1,28 @@
1
- export const mdDivider = () => `\n---\n`;
2
1
  export const mdSection = (title, body) => {
3
2
  const trimmed = body.trim();
4
- return trimmed.length === 0 ? `## ${title}\n` : `## ${title}\n${trimmed}\n`;
3
+ return `<${title}>${trimmed}</${title}>`;
5
4
  };
6
- export const jsonBlock = (label, value) => `${label}:\n${JSON.stringify(value ?? null, null, 2)}\n`;
5
+ export const jsonBlock = (label, value) => `${label}:${JSON.stringify(value ?? null)}\n`;
7
6
  export const projectStateNote = (isNewProject, role) => {
8
7
  if (role === "planner") {
9
8
  return isNewProject
10
- ? "The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify it per the PM plan; ensure there are no traces of boilerplate in the final project."
11
- : "The project has already gone through some stages of modification. Create tasks only for the latest PM recommendations and avoid rework.";
9
+ ? "The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify project according to PM plan and context; remove boilerplate traces."
10
+ : "Plan only latest PM changes; avoid rework";
12
11
  }
13
12
  return isNewProject
14
- ? "The project is currently a boilerplate. Implement the task cleanly while removing unnecessary boilerplate patterns."
15
- : "The project has existing modifications. Implement the task incrementally without breaking existing architecture.";
13
+ ? "The project is currently a boilerplate. Implement task cleanly while removing boilerplate patterns."
14
+ : "Implement task incrementally without breaking existing architecture.";
16
15
  };
17
16
  export const renderPlannerTaskFormatSection = () => mdSection("Task Format (STRICT)", `
18
- When you are done planning, you MUST call submit_planner_tasks with:
17
+ After planning, Call submit_planner_tasks with:
19
18
 
20
19
  {
21
20
  "planner_tasks": [
22
21
  {
23
- "description": "DETAILED instruction. Include exact paths + expected end state. No code blocks.",
24
- "targets": ["Paths that WILL be modified or MUST be referred to."]
22
+ "description": "Exact changes + paths. No code",
23
+ "targets": ["Paths that to be modified or referenced"]
25
24
  }
26
25
  ]
27
26
  }
28
27
  `.trim());
29
- export const plannerObjectives = (target) => mdSection("Objectives", `
30
- 1) Create atomic, deterministic tasks to ${target == "validator" ? "resolve ALL validation errors" : "implement PM Plan"} which should include exact file paths to create/modify
31
- 2) Ensure instructions are foolproof for code-gen execution.
32
- 3) Use incremental updates; minimize full rewrites.
33
- 4) Use existing code context wherever possible.
34
- 5) Be token-efficient: concise but technically complete.
35
- 6) DO NOT write code, you have to just plan the tasks
36
- `.trim());
37
28
  //# sourceMappingURL=promptParts.helper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promptParts.helper.js","sourceRoot":"","sources":["../../../../src/ai/prompts/helpers/promptParts.helper.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC;AAEzC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,IAAY,EAAE,EAAE;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,OAAO,IAAI,CAAC;AAC9E,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,KAAc,EAAE,EAAE,CACzD,GAAG,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAE3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,YAAqB,EAAE,IAAgB,EAAE,EAAE;IAC1E,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,YAAY;YACjB,CAAC,CAAC,2MAA2M;YAC7M,CAAC,CAAC,yIAAyI,CAAC;IAChJ,CAAC;IAED,OAAO,YAAY;QACjB,CAAC,CAAC,qHAAqH;QACvH,CAAC,CAAC,kHAAkH,CAAC;AACzH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,EAAE,CACjD,SAAS,CACP,sBAAsB,EACtB;;;;;;;;;;;KAWC,CAAC,IAAI,EAAE,CACT,CAAC;AAEJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAkB,EAAE,EAAE,CACtD,SAAS,CACP,YAAY,EACZ;2CACuC,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,mBAAmB;;;;;;OAMjH,CAAC,IAAI,EAAE,CACX,CAAC","sourcesContent":["export type PromptRole = \"planner\" | \"codegen\" | \"validator\";\n\nexport const mdDivider = () => `\\n---\\n`;\n\nexport const mdSection = (title: string, body: string) => {\n const trimmed = body.trim();\n return trimmed.length === 0 ? `## ${title}\\n` : `## ${title}\\n${trimmed}\\n`;\n};\n\nexport const jsonBlock = (label: string, value: unknown) =>\n `${label}:\\n${JSON.stringify(value ?? null, null, 2)}\\n`;\n\nexport const projectStateNote = (isNewProject: boolean, role: PromptRole) => {\n if (role === \"planner\") {\n return isNewProject\n ? \"The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify it per the PM plan; ensure there are no traces of boilerplate in the final project.\"\n : \"The project has already gone through some stages of modification. Create tasks only for the latest PM recommendations and avoid rework.\";\n }\n\n return isNewProject\n ? \"The project is currently a boilerplate. Implement the task cleanly while removing unnecessary boilerplate patterns.\"\n : \"The project has existing modifications. Implement the task incrementally without breaking existing architecture.\";\n};\n\nexport const renderPlannerTaskFormatSection = () =>\n mdSection(\n \"Task Format (STRICT)\",\n `\nWhen you are done planning, you MUST call submit_planner_tasks with:\n\n{\n \"planner_tasks\": [\n {\n \"description\": \"DETAILED instruction. Include exact paths + expected end state. No code blocks.\",\n \"targets\": [\"Paths that WILL be modified or MUST be referred to.\"]\n }\n ]\n}\n `.trim(),\n );\n\nexport const plannerObjectives = (target: PromptRole) =>\n mdSection(\n \"Objectives\",\n `\n1) Create atomic, deterministic tasks to ${target == \"validator\" ? \"resolve ALL validation errors\" : \"implement PM Plan\"} which should include exact file paths to create/modify \n2) Ensure instructions are foolproof for code-gen execution.\n3) Use incremental updates; minimize full rewrites.\n4) Use existing code context wherever possible.\n5) Be token-efficient: concise but technically complete.\n6) DO NOT write code, you have to just plan the tasks\n `.trim(),\n );\n"]}
1
+ {"version":3,"file":"promptParts.helper.js","sourceRoot":"","sources":["../../../../src/ai/prompts/helpers/promptParts.helper.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,IAAY,EAAE,EAAE;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,GAAG,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,KAAc,EAAE,EAAE,CACzD,GAAG,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC;AAEhD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,YAAqB,EAAE,IAAgB,EAAE,EAAE;IAC1E,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,YAAY;YACjB,CAAC,CAAC,4LAA4L;YAC9L,CAAC,CAAC,2CAA2C,CAAC;IAClD,CAAC;IAED,OAAO,YAAY;QACjB,CAAC,CAAC,qGAAqG;QACvG,CAAC,CAAC,sEAAsE,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,EAAE,CACjD,SAAS,CACP,sBAAsB,EACtB;;;;;;;;;;;KAWC,CAAC,IAAI,EAAE,CACT,CAAC","sourcesContent":["export type PromptRole = \"planner\" | \"codegen\" | \"validator\";\n\nexport const mdSection = (title: string, body: string) => {\n const trimmed = body.trim();\n return `<${title}>${trimmed}</${title}>`;\n};\n\nexport const jsonBlock = (label: string, value: unknown) =>\n `${label}:${JSON.stringify(value ?? null)}\\n`;\n\nexport const projectStateNote = (isNewProject: boolean, role: PromptRole) => {\n if (role === \"planner\") {\n return isNewProject\n ? \"The project you are given is currently a boilerplate project that contains some existing code. Create tasks to modify project according to PM plan and context; remove boilerplate traces.\"\n : \"Plan only latest PM changes; avoid rework\";\n }\n\n return isNewProject\n ? \"The project is currently a boilerplate. Implement task cleanly while removing boilerplate patterns.\"\n : \"Implement task incrementally without breaking existing architecture.\";\n};\n\nexport const renderPlannerTaskFormatSection = () =>\n mdSection(\n \"Task Format (STRICT)\",\n `\nAfter planning, Call submit_planner_tasks with:\n\n{\n \"planner_tasks\": [\n {\n \"description\": \"Exact changes + paths. No code\",\n \"targets\": [\"Paths that to be modified or referenced\"]\n }\n ]\n}\n `.trim(),\n );\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"planner.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/planner.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAUrD,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,oBAAoB,WA+EzD,CAAC"}
1
+ {"version":3,"file":"planner.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/planner.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AASrD,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,oBAAoB,WA+DzD,CAAC"}
@@ -1,48 +1,44 @@
1
1
  import { plannerExamples } from "./examples/planner.examples.js";
2
- import { jsonBlock, mdSection, plannerObjectives, projectStateNote, renderPlannerTaskFormatSection, } from "./helpers/promptParts.helper.js";
2
+ import { jsonBlock, mdSection, projectStateNote, renderPlannerTaskFormatSection, } from "./helpers/promptParts.helper.js";
3
3
  export const plannerPrompt = (params) => {
4
4
  const { planTasks, collectedContext, plannerIndex, isNewProject } = params;
5
- const intialPrompt = `
6
- You are a senior software architect.
7
- Based on the provided PM plan and code context, generate a detailed technical implementation plan.
8
- Provide precise, step-by-step instructions for a code-generation agent; ensure tasks are explicit, atomic, and ordered.
9
- ${projectStateNote(isNewProject, "planner")}
10
- `.trim();
11
- const objectives = plannerObjectives("planner");
12
- const context = mdSection("Inputs (Authoritative)", [
13
- jsonBlock("Project Context (User preferences etc.)", collectedContext ?? {}),
14
- ].join("\n"));
15
- const projectConfiguration = mdSection("Project Configuration", [
16
- jsonBlock("FRAMEWORK CONFIG", plannerIndex.projectConfigs.frameworkConfig),
17
- jsonBlock("RUNTIME CONFIG", plannerIndex.projectConfigs.runtimeConfig),
18
- jsonBlock("TOOLING CONFIG", plannerIndex.projectConfigs.toolingConfig),
19
- jsonBlock("RENDERING CONFIGURATION", plannerIndex.projectConfigs.renderingConfig),
20
- ].join("\n"));
21
- const toolsInfo = mdSection("Tools", `
22
- You are provided access to the following tools and use them to plan coding tasks.
23
-
24
- read_file: Use it to read a file from the codebase.
5
+ const system = `
6
+ You are a senior software architect creating implementation tasks.
25
7
 
26
- search: Use it to search for code in the codebase.
27
-
28
- list_dir: Use it to list the directory structure of the codebase.
29
-
30
- submit_planner_tasks: Use it to finalize and return the planner tasks for the code-generation agent.
8
+ Rules:
9
+ - Create atomic, deterministic tasks.
10
+ - Include exact file paths to create/modify.
11
+ - Prefer incremental edits over rewrites.
12
+ - Reuse existing code/patterns.
13
+ - Be concise but complete.
14
+ - Do not write code.
15
+ - Tasks must be directly executable by codegen agents.
16
+
17
+ ${projectStateNote(isNewProject, "planner")}
18
+ `.trim();
19
+ const planTasksInfo = mdSection("PM Tasks", jsonBlock("Tasks", planTasks ?? []));
20
+ const toolsInfo = mdSection("Tools", `
21
+ - read_file: read file
22
+ - search: search codebase
23
+ - list_dir: list dirs
24
+ - submit_planner_tasks: Finalize planner output
31
25
  `);
32
- const planTasksInfo = mdSection("Plan Tasks", jsonBlock("Plan Tasks", planTasks ?? []));
33
26
  const rendering = renderPlannerTaskFormatSection();
34
- const examples = plannerExamples;
35
- const plannerClosingNote = "Focus on clarity, minimalism, and correctness. Your plan will directly determine the success of the system.";
27
+ const projectConfiguration = mdSection("Project Config", [
28
+ jsonBlock("framework", plannerIndex.projectConfigs.frameworkConfig),
29
+ jsonBlock("runtime", plannerIndex.projectConfigs.runtimeConfig),
30
+ jsonBlock("tooling", plannerIndex.projectConfigs.toolingConfig),
31
+ jsonBlock("rendering", plannerIndex.projectConfigs.renderingConfig),
32
+ ].join("\n"));
33
+ const context = mdSection("Relevant Context", jsonBlock("context", collectedContext ?? {}));
36
34
  const sections = [
37
- intialPrompt,
38
- objectives,
39
- context,
40
- projectConfiguration,
35
+ system,
36
+ planTasksInfo,
41
37
  toolsInfo,
42
38
  rendering,
43
- examples,
44
- planTasksInfo,
45
- plannerClosingNote,
39
+ projectConfiguration,
40
+ context,
41
+ plannerExamples,
46
42
  ];
47
43
  return sections.join("\n\n---\n\n");
48
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"planner.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/planner.prompt.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,8BAA8B,GAC/B,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA4B,EAAE,EAAE;IAC5D,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAE3E,MAAM,YAAY,GAAG;;;;EAIrB,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;KACtC,CAAC,IAAI,EAAE,CAAC;IAEX,MAAM,UAAU,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,SAAS,CACvB,wBAAwB,EACxB;QACE,SAAS,CACP,yCAAyC,EACzC,gBAAgB,IAAI,EAAE,CACvB;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,oBAAoB,GAAG,SAAS,CACpC,uBAAuB,EACvB;QACE,SAAS,CACP,kBAAkB,EAClB,YAAY,CAAC,cAAc,CAAC,eAAe,CAC5C;QACD,SAAS,CAAC,gBAAgB,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QACtE,SAAS,CAAC,gBAAgB,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QACtE,SAAS,CACP,yBAAyB,EACzB,YAAY,CAAC,cAAc,CAAC,eAAe,CAC5C;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EAEP;;;;;;;;;;KAUC,CACF,CAAC;IAEF,MAAM,aAAa,GAAG,SAAS,CAC7B,YAAY,EACZ,SAAS,CAAC,YAAY,EAAE,SAAS,IAAI,EAAE,CAAC,CACzC,CAAC;IAEF,MAAM,SAAS,GAAG,8BAA8B,EAAE,CAAC;IAEnD,MAAM,QAAQ,GAAG,eAAe,CAAC;IAEjC,MAAM,kBAAkB,GACtB,6GAA6G,CAAC;IAEhH,MAAM,QAAQ,GAAG;QACf,YAAY;QACZ,UAAU;QACV,OAAO;QACP,oBAAoB;QACpB,SAAS;QACT,SAAS;QACT,QAAQ;QACR,aAAa;QACb,kBAAkB;KACnB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { CollectedContext } from \"../../types/context.types.js\";\r\nimport { PlannerIndex } from \"../../types/public.js\";\r\nimport { plannerExamples } from \"./examples/planner.examples.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n plannerObjectives,\r\n projectStateNote,\r\n renderPlannerTaskFormatSection,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type PlanNodePromptParams = {\r\n planTasks: unknown[];\r\n collectedContext: CollectedContext;\r\n plannerIndex: PlannerIndex;\r\n isNewProject: boolean;\r\n};\r\n\r\nexport const plannerPrompt = (params: PlanNodePromptParams) => {\r\n const { planTasks, collectedContext, plannerIndex, isNewProject } = params;\r\n\r\n const intialPrompt = `\r\nYou are a senior software architect.\r\nBased on the provided PM plan and code context, generate a detailed technical implementation plan.\r\nProvide precise, step-by-step instructions for a code-generation agent; ensure tasks are explicit, atomic, and ordered.\r\n${projectStateNote(isNewProject, \"planner\")}\r\n `.trim();\r\n\r\n const objectives = plannerObjectives(\"planner\");\r\n\r\n const context = mdSection(\r\n \"Inputs (Authoritative)\",\r\n [\r\n jsonBlock(\r\n \"Project Context (User preferences etc.)\",\r\n collectedContext ?? {},\r\n ),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Configuration\",\r\n [\r\n jsonBlock(\r\n \"FRAMEWORK CONFIG\",\r\n plannerIndex.projectConfigs.frameworkConfig,\r\n ),\r\n jsonBlock(\"RUNTIME CONFIG\", plannerIndex.projectConfigs.runtimeConfig),\r\n jsonBlock(\"TOOLING CONFIG\", plannerIndex.projectConfigs.toolingConfig),\r\n jsonBlock(\r\n \"RENDERING CONFIGURATION\",\r\n plannerIndex.projectConfigs.renderingConfig,\r\n ),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n\r\n `\r\n You are provided access to the following tools and use them to plan coding tasks.\r\n \r\n read_file: Use it to read a file from the codebase.\r\n\r\n search: Use it to search for code in the codebase.\r\n \r\n list_dir: Use it to list the directory structure of the codebase.\r\n \r\n submit_planner_tasks: Use it to finalize and return the planner tasks for the code-generation agent.\r\n `,\r\n );\r\n\r\n const planTasksInfo = mdSection(\r\n \"Plan Tasks\",\r\n jsonBlock(\"Plan Tasks\", planTasks ?? []),\r\n );\r\n\r\n const rendering = renderPlannerTaskFormatSection();\r\n\r\n const examples = plannerExamples;\r\n\r\n const plannerClosingNote =\r\n \"Focus on clarity, minimalism, and correctness. Your plan will directly determine the success of the system.\";\r\n\r\n const sections = [\r\n intialPrompt,\r\n objectives,\r\n context,\r\n projectConfiguration,\r\n toolsInfo,\r\n rendering,\r\n examples,\r\n planTasksInfo,\r\n plannerClosingNote,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
1
+ {"version":3,"file":"planner.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/planner.prompt.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,8BAA8B,GAC/B,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA4B,EAAE,EAAE;IAC5D,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAE3E,MAAM,MAAM,GAAG;;;;;;;;;;;;MAYX,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;GAC5C,CAAC,IAAI,EAAE,CAAC;IACT,MAAM,aAAa,GAAG,SAAS,CAC7B,UAAU,EACV,SAAS,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC,CACpC,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EACP;;;;;KAKC,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,8BAA8B,EAAE,CAAC;IAEnD,MAAM,oBAAoB,GAAG,SAAS,CACpC,gBAAgB,EAChB;QACE,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;QAEnE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QAE/D,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QAE/D,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;KACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,OAAO,GAAG,SAAS,CACvB,kBAAkB,EAClB,SAAS,CAAC,SAAS,EAAE,gBAAgB,IAAI,EAAE,CAAC,CAC7C,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,MAAM;QACN,aAAa;QACb,SAAS;QACT,SAAS;QACT,oBAAoB;QACpB,OAAO;QACP,eAAe;KAChB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { CollectedContext } from \"../../types/context.types.js\";\r\nimport { PlannerIndex } from \"../../types/public.js\";\r\nimport { plannerExamples } from \"./examples/planner.examples.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n projectStateNote,\r\n renderPlannerTaskFormatSection,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type PlanNodePromptParams = {\r\n planTasks: unknown[];\r\n collectedContext: CollectedContext;\r\n plannerIndex: PlannerIndex;\r\n isNewProject: boolean;\r\n};\r\n\r\nexport const plannerPrompt = (params: PlanNodePromptParams) => {\r\n const { planTasks, collectedContext, plannerIndex, isNewProject } = params;\r\n\r\n const system = `\r\n You are a senior software architect creating implementation tasks.\r\n\r\n Rules:\r\n - Create atomic, deterministic tasks.\r\n - Include exact file paths to create/modify.\r\n - Prefer incremental edits over rewrites.\r\n - Reuse existing code/patterns.\r\n - Be concise but complete.\r\n - Do not write code.\r\n - Tasks must be directly executable by codegen agents.\r\n\r\n ${projectStateNote(isNewProject, \"planner\")}\r\n `.trim();\r\n const planTasksInfo = mdSection(\r\n \"PM Tasks\",\r\n jsonBlock(\"Tasks\", planTasks ?? []),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n `\r\n - read_file: read file\r\n - search: search codebase\r\n - list_dir: list dirs\r\n - submit_planner_tasks: Finalize planner output\r\n `,\r\n );\r\n\r\n const rendering = renderPlannerTaskFormatSection();\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Config\",\r\n [\r\n jsonBlock(\"framework\", plannerIndex.projectConfigs.frameworkConfig),\r\n\r\n jsonBlock(\"runtime\", plannerIndex.projectConfigs.runtimeConfig),\r\n\r\n jsonBlock(\"tooling\", plannerIndex.projectConfigs.toolingConfig),\r\n\r\n jsonBlock(\"rendering\", plannerIndex.projectConfigs.renderingConfig),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const context = mdSection(\r\n \"Relevant Context\",\r\n jsonBlock(\"context\", collectedContext ?? {}),\r\n );\r\n\r\n const sections = [\r\n system,\r\n planTasksInfo,\r\n toolsInfo,\r\n rendering,\r\n projectConfiguration,\r\n context,\r\n plannerExamples,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"validator.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/validator.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQvD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,0BAA0B,WAmFjE,CAAC"}
1
+ {"version":3,"file":"validator.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/validator.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAOvD,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,0BAA0B,WA0EjE,CAAC"}
@@ -1,54 +1,53 @@
1
- import { jsonBlock, mdSection, plannerObjectives, renderPlannerTaskFormatSection, } from "./helpers/promptParts.helper.js";
1
+ import { jsonBlock, mdSection, renderPlannerTaskFormatSection, } from "./helpers/promptParts.helper.js";
2
2
  export const validatorPrompt = (params) => {
3
3
  const { errors, history, validatorIndex } = params;
4
- const initialPrompt = `You are a senior software engineer.
5
- Based on the provided validation errors and fix history, generate a detailed technical implementation plan.
6
- Provide precise, step-by-step instructions for a code-generation agent; ensure tasks are explicit and highly granular.
7
- `.trim();
8
- const objectives = plannerObjectives("validator");
9
- const projectConfiguration = mdSection("Project Configuration", [
10
- jsonBlock("FRAMEWORK CONFIG", validatorIndex.projectConfigs.frameworkConfig),
11
- jsonBlock("RUNTIME CONFIG", validatorIndex.projectConfigs.runtimeConfig),
12
- jsonBlock("TOOLING CONFIG", validatorIndex.projectConfigs.toolingConfig),
13
- jsonBlock("RENDERING CONFIGURATION", validatorIndex.projectConfigs.renderingConfig),
14
- ].join("\n"));
4
+ const system = `
5
+ You are a senior software engineer creating fix tasks for validation failures.
6
+
7
+ Rules:
8
+ - Fix ALL validation errors.
9
+ - Create atomic, deterministic tasks.
10
+ - Include exact file paths.
11
+ - Prefer incremental edits over rewrites.
12
+ - Reuse existing code/patterns.
13
+ - Be concise but complete.
14
+ - Do not write code.
15
+ - Tasks must be directly executable by codegen agents.
16
+ `.trim();
15
17
  const renderedErrors = errors.length === 0
16
- ? "- No validation errors were provided."
18
+ ? "none"
17
19
  : errors
18
- .map((error) => `- Type: ${error.type}\n File: ${error.filePath}\n Message: ${error.message}`)
20
+ .map((e) => `type:${e.type} file:${e.filePath} msg:${e.message}`)
19
21
  .join("\n");
20
22
  const renderedHistory = history.length === 0
21
- ? "- No previous fixes attempted."
22
- : history
23
- .map((h) => `- File: ${h.file}\n Fix Attempted: ${h.fix}`)
24
- .join("\n");
25
- const errorsInfo = mdSection("Inputs (Authoritative)", `
26
- Validation Errors:
27
- ${renderedErrors}
23
+ ? "none"
24
+ : history.map((h) => `file:${h.file} fix:${h.fix}`).join("\n");
25
+ const errorsInfo = mdSection("Validation", `
26
+ Errors:
27
+ ${renderedErrors}
28
28
 
29
- Fix History:
30
- ${renderedHistory}
31
-
32
- `.trim());
29
+ History:
30
+ ${renderedHistory}
31
+ `.trim());
33
32
  const toolsInfo = mdSection("Tools", `
34
- You are provided access to the following tools and use them to plan coding tasks.
35
-
36
- read_file: Use it to read a file from the codebase.
37
-
38
- search: Use it to search for code in the codebase.
39
-
40
- list_dir: Use it to list the directory structure of the codebase.
41
-
42
- submit_planner_tasks: Use it to finalize and return the planner tasks for the code-generation agent.
43
- `);
33
+ - read_file: read file
34
+ - search: search codebase
35
+ - list_dir: list dirs
36
+ - submit_planner_tasks: submit tasks
37
+ `.trim());
44
38
  const rendering = renderPlannerTaskFormatSection();
39
+ const projectConfiguration = mdSection("Project Config", [
40
+ jsonBlock("framework", validatorIndex.projectConfigs.frameworkConfig),
41
+ jsonBlock("runtime", validatorIndex.projectConfigs.runtimeConfig),
42
+ jsonBlock("tooling", validatorIndex.projectConfigs.toolingConfig),
43
+ jsonBlock("rendering", validatorIndex.projectConfigs.renderingConfig),
44
+ ].join("\n"));
45
45
  const sections = [
46
- initialPrompt,
47
- objectives,
48
- projectConfiguration,
46
+ system,
47
+ errorsInfo,
49
48
  toolsInfo,
50
49
  rendering,
51
- errorsInfo,
50
+ projectConfiguration,
52
51
  ];
53
52
  return sections.join("\n\n---\n\n");
54
53
  };
@@ -1 +1 @@
1
- {"version":3,"file":"validator.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/validator.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,SAAS,EACT,iBAAiB,EACjB,8BAA8B,GAC/B,MAAM,iCAAiC,CAAC;AAYzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAkC,EAAE,EAAE;IACpE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IAEnD,MAAM,aAAa,GAAG;;;KAGnB,CAAC,IAAI,EAAE,CAAC;IAEX,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,oBAAoB,GAAG,SAAS,CACpC,uBAAuB,EACvB;QACE,SAAS,CACP,kBAAkB,EAClB,cAAc,CAAC,cAAc,CAAC,eAAe,CAC9C;QACD,SAAS,CAAC,gBAAgB,EAAE,cAAc,CAAC,cAAc,CAAC,aAAa,CAAC;QACxE,SAAS,CAAC,gBAAgB,EAAE,cAAc,CAAC,cAAc,CAAC,aAAa,CAAC;QACxE,SAAS,CACP,yBAAyB,EACzB,cAAc,CAAC,cAAc,CAAC,eAAe,CAC9C;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,cAAc,GAClB,MAAM,CAAC,MAAM,KAAK,CAAC;QACjB,CAAC,CAAC,uCAAuC;QACzC,CAAC,CAAC,MAAM;aACH,GAAG,CACF,CAAC,KAAK,EAAE,EAAE,CACR,WAAW,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,QAAQ,gBAAgB,KAAK,CAAC,OAAO,EAAE,CAClF;aACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,eAAe,GACnB,OAAO,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,CAAC,gCAAgC;QAClC,CAAC,CAAC,OAAO;aACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,IAAI,sBAAsB,CAAC,CAAC,GAAG,EAAE,CAAC;aAC1D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,UAAU,GAAG,SAAS,CAC1B,wBAAwB,EACxB;;EAEF,cAAc;;;EAGd,eAAe;;OAEV,CAAC,IAAI,EAAE,CACX,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EAEP;;;;;;;;;;KAUC,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,8BAA8B,EAAE,CAAC;IAEnD,MAAM,QAAQ,GAAG;QACf,aAAa;QACb,UAAU;QACV,oBAAoB;QACpB,SAAS;QACT,SAAS;QACT,UAAU;KACX,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { ValidatorIndex } from \"../../types/public.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n plannerObjectives,\r\n renderPlannerTaskFormatSection,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type ValidationNodePromptParams = {\r\n errors: Array<{\r\n type?: string | null;\r\n filePath?: string | null;\r\n message?: string | null;\r\n }>;\r\n history: Array<{ file?: string; fix?: string }>;\r\n validatorIndex: ValidatorIndex;\r\n};\r\n\r\nexport const validatorPrompt = (params: ValidationNodePromptParams) => {\r\n const { errors, history, validatorIndex } = params;\r\n\r\n const initialPrompt = `You are a senior software engineer.\r\nBased on the provided validation errors and fix history, generate a detailed technical implementation plan.\r\nProvide precise, step-by-step instructions for a code-generation agent; ensure tasks are explicit and highly granular.\r\n `.trim();\r\n\r\n const objectives = plannerObjectives(\"validator\");\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Configuration\",\r\n [\r\n jsonBlock(\r\n \"FRAMEWORK CONFIG\",\r\n validatorIndex.projectConfigs.frameworkConfig,\r\n ),\r\n jsonBlock(\"RUNTIME CONFIG\", validatorIndex.projectConfigs.runtimeConfig),\r\n jsonBlock(\"TOOLING CONFIG\", validatorIndex.projectConfigs.toolingConfig),\r\n jsonBlock(\r\n \"RENDERING CONFIGURATION\",\r\n validatorIndex.projectConfigs.renderingConfig,\r\n ),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const renderedErrors =\r\n errors.length === 0\r\n ? \"- No validation errors were provided.\"\r\n : errors\r\n .map(\r\n (error) =>\r\n `- Type: ${error.type}\\n File: ${error.filePath}\\n Message: ${error.message}`,\r\n )\r\n .join(\"\\n\");\r\n\r\n const renderedHistory =\r\n history.length === 0\r\n ? \"- No previous fixes attempted.\"\r\n : history\r\n .map((h) => `- File: ${h.file}\\n Fix Attempted: ${h.fix}`)\r\n .join(\"\\n\");\r\n\r\n const errorsInfo = mdSection(\r\n \"Inputs (Authoritative)\",\r\n `\r\nValidation Errors:\r\n${renderedErrors}\r\n\r\nFix History:\r\n${renderedHistory}\r\n\r\n `.trim(),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n\r\n `\r\n You are provided access to the following tools and use them to plan coding tasks.\r\n \r\n read_file: Use it to read a file from the codebase.\r\n\r\n search: Use it to search for code in the codebase.\r\n \r\n list_dir: Use it to list the directory structure of the codebase.\r\n \r\n submit_planner_tasks: Use it to finalize and return the planner tasks for the code-generation agent.\r\n `,\r\n );\r\n\r\n const rendering = renderPlannerTaskFormatSection();\r\n\r\n const sections = [\r\n initialPrompt,\r\n objectives,\r\n projectConfiguration,\r\n toolsInfo,\r\n rendering,\r\n errorsInfo,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
1
+ {"version":3,"file":"validator.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/validator.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,SAAS,EACT,8BAA8B,GAC/B,MAAM,iCAAiC,CAAC;AAYzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAkC,EAAE,EAAE;IACpE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IAEnD,MAAM,MAAM,GAAG;;;;;;;;;;;;GAYd,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,cAAc,GAClB,MAAM,CAAC,MAAM,KAAK,CAAC;QACjB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM;aACH,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,QAAQ,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;aAChE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,eAAe,GACnB,OAAO,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEnE,MAAM,UAAU,GAAG,SAAS,CAC1B,YAAY,EACZ;;QAEI,cAAc;;;QAGd,eAAe;KAClB,CAAC,IAAI,EAAE,CACT,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EACP;;;;;KAKC,CAAC,IAAI,EAAE,CACT,CAAC;IAEF,MAAM,SAAS,GAAG,8BAA8B,EAAE,CAAC;IAEnD,MAAM,oBAAoB,GAAG,SAAS,CACpC,gBAAgB,EAChB;QACE,SAAS,CAAC,WAAW,EAAE,cAAc,CAAC,cAAc,CAAC,eAAe,CAAC;QAErE,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,cAAc,CAAC,aAAa,CAAC;QAEjE,SAAS,CAAC,SAAS,EAAE,cAAc,CAAC,cAAc,CAAC,aAAa,CAAC;QAEjE,SAAS,CAAC,WAAW,EAAE,cAAc,CAAC,cAAc,CAAC,eAAe,CAAC;KACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,MAAM;QACN,UAAU;QACV,SAAS;QACT,SAAS;QACT,oBAAoB;KACrB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { ValidatorIndex } from \"../../types/public.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n renderPlannerTaskFormatSection,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type ValidationNodePromptParams = {\r\n errors: Array<{\r\n type?: string | null;\r\n filePath?: string | null;\r\n message?: string | null;\r\n }>;\r\n history: Array<{ file?: string; fix?: string }>;\r\n validatorIndex: ValidatorIndex;\r\n};\r\n\r\nexport const validatorPrompt = (params: ValidationNodePromptParams) => {\r\n const { errors, history, validatorIndex } = params;\r\n\r\n const system = `\r\n You are a senior software engineer creating fix tasks for validation failures.\r\n\r\n Rules:\r\n - Fix ALL validation errors.\r\n - Create atomic, deterministic tasks.\r\n - Include exact file paths.\r\n - Prefer incremental edits over rewrites.\r\n - Reuse existing code/patterns.\r\n - Be concise but complete.\r\n - Do not write code.\r\n - Tasks must be directly executable by codegen agents.\r\n `.trim();\r\n\r\n const renderedErrors =\r\n errors.length === 0\r\n ? \"none\"\r\n : errors\r\n .map((e) => `type:${e.type} file:${e.filePath} msg:${e.message}`)\r\n .join(\"\\n\");\r\n\r\n const renderedHistory =\r\n history.length === 0\r\n ? \"none\"\r\n : history.map((h) => `file:${h.file} fix:${h.fix}`).join(\"\\n\");\r\n\r\n const errorsInfo = mdSection(\r\n \"Validation\",\r\n `\r\n Errors:\r\n ${renderedErrors}\r\n\r\n History:\r\n ${renderedHistory}\r\n `.trim(),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n `\r\n - read_file: read file\r\n - search: search codebase\r\n - list_dir: list dirs\r\n - submit_planner_tasks: submit tasks\r\n `.trim(),\r\n );\r\n\r\n const rendering = renderPlannerTaskFormatSection();\r\n\r\n const projectConfiguration = mdSection(\r\n \"Project Config\",\r\n [\r\n jsonBlock(\"framework\", validatorIndex.projectConfigs.frameworkConfig),\r\n\r\n jsonBlock(\"runtime\", validatorIndex.projectConfigs.runtimeConfig),\r\n\r\n jsonBlock(\"tooling\", validatorIndex.projectConfigs.toolingConfig),\r\n\r\n jsonBlock(\"rendering\", validatorIndex.projectConfigs.renderingConfig),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const sections = [\r\n system,\r\n errorsInfo,\r\n toolsInfo,\r\n rendering,\r\n projectConfiguration,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAWjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAG3C,OAAO,MAAM,EAAE,UAAU,MAAM,EAAE,SAAS,cAAc;;;;;;;;;;;;;;;;;;;;;;EAkFvE,CAAC"}
1
+ {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAWjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAG3C,OAAO,MAAM,EAAE,UAAU,MAAM,EAAE,SAAS,cAAc;;;;;;;;;;;;;;;;;;;;;;EAmFvE,CAAC"}
@@ -63,7 +63,7 @@ export const createInsertElementImpl = (deps) => {
63
63
  if (!parent)
64
64
  return { success: false, error: "parent not found" };
65
65
  const anyParent = parent;
66
- if (!Array.isArray(anyParent.children))
66
+ if (!anyParent.children || !Array.isArray(anyParent.children))
67
67
  anyParent.children = [];
68
68
  anyParent.children.push(toInsert);
69
69
  const after = stringifyPageConfigJson({ elements });
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n getPageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, parentId: string, element: BuilderElement) => {\n const parsedArgs = InsertElementArgsZod.safeParse({\n route,\n parent_id: parentId,\n element,\n });\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parentId ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n let configPath: string;\n try {\n configPath = getPageConfigJsonPath(workspaceRoot, route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n const toInsert = JSON.parse(\n JSON.stringify(element ?? null),\n ) as BuilderElement;\n await resolveUnsplashImagesDeep(toInsert);\n ensureElementIds([toInsert], existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!Array.isArray(anyParent.children)) anyParent.children = [];\n (anyParent.children as BuilderElement[]).push(toInsert);\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert as any).id,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n getPageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, parentId: string, element: BuilderElement) => {\n const parsedArgs = InsertElementArgsZod.safeParse({\n route,\n parent_id: parentId,\n element,\n });\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parentId ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n let configPath: string;\n try {\n configPath = getPageConfigJsonPath(workspaceRoot, route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n const toInsert = JSON.parse(\n JSON.stringify(element ?? null),\n ) as BuilderElement;\n await resolveUnsplashImagesDeep(toInsert);\n ensureElementIds([toInsert], existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n (anyParent.children as BuilderElement[]).push(toInsert);\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert as any).id,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,aAAa,8FAUhB,CAAC;AA2HX,eAAO,MAAM,oBAAoB,EAAE,GAAkC,CAAC;AAEtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;CAuB/B,CAAC"}
1
+ {"version":3,"file":"insertElement.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,aAAa,8FAUhB,CAAC;AA0HX,eAAO,MAAM,oBAAoB,EAAE,GAAkC,CAAC;AAEtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;CAuB/B,CAAC"}
@@ -91,32 +91,32 @@ const buildBuilderElementSchema = (depth) => {
91
91
  type: {
92
92
  type: Type.STRING,
93
93
  enum: ELEMENT_TYPES,
94
- description: "Element type to render. 'text' renders a <p>, 'image' renders an <img>, 'link' renders an <a>, 'icon' renders a Lucide icon, 'fragment' renders children only.",
94
+ description: "Element type to render. Use 'text' for <p>, 'image' forn <img>, 'link' for <a>, 'icon' for Lucide icon, 'fragment' renders children only",
95
95
  },
96
96
  className: {
97
97
  type: Type.STRING,
98
- description: "Tailwind CSS className applied to the rendered element (Tailwind only).",
98
+ description: "Tailwind CSS className (Tailwind only)",
99
99
  },
100
100
  visible: {
101
101
  type: Type.BOOLEAN,
102
- description: "Whether the element should be shown.",
102
+ description: "Visibility flag",
103
103
  },
104
104
  props: BuilderElementPropsSchema,
105
105
  children: {
106
106
  type: Type.ARRAY,
107
- description: "Nested children. Each child is another element and can itself have children (children[].children[]...).",
107
+ description: "Child elements. Each child can itself have children (children[].children[]...)",
108
108
  items: depth > 0
109
109
  ? buildBuilderElementSchema(depth - 1)
110
110
  : {
111
111
  type: Type.OBJECT,
112
- description: "Max depth reached in tool schema. If you need deeper nesting, insert the parent first, then insert children using the returned inserted_id as parent_id.",
112
+ description: "Max depth reached. Insert deeper children separately using the returned inserted_id as parent_id",
113
113
  },
114
114
  },
115
115
  },
116
116
  required: ["type"],
117
117
  };
118
118
  };
119
- export const BuilderElementSchema = buildBuilderElementSchema(6);
119
+ export const BuilderElementSchema = buildBuilderElementSchema(4);
120
120
  export const InsertElementSchema = {
121
121
  name: "insert_element",
122
122
  description: "Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.",
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const ELEMENT_TYPES = [\r\n \"fragment\",\r\n \"div\",\r\n \"text\",\r\n \"image\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"link\",\r\n \"icon\",\r\n] as const;\r\n\r\nconst OnClickActionSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n kind: {\r\n type: Type.STRING,\r\n enum: [\"route\", \"back\", \"reload\", \"external\"],\r\n description:\r\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description:\r\n \"URL to navigate to (used for kind='route' and kind='external').\",\r\n },\r\n replace: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='route': replace history instead of pushing.\",\r\n },\r\n newTab: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='external': open link in a new tab.\",\r\n },\r\n },\r\n required: [\"kind\"],\r\n};\r\n\r\nconst BuilderElementPropsSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n onClick: OnClickActionSchema,\r\n text: {\r\n type: Type.STRING,\r\n description:\r\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description: \"For 'link': the href attribute (defaults to '#').\",\r\n },\r\n placeholder: {\r\n type: Type.STRING,\r\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\r\n },\r\n alt: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\r\n },\r\n target: {\r\n type: Type.STRING,\r\n description: \"For 'link': target attribute (e.g. '_blank').\",\r\n },\r\n rel: {\r\n type: Type.STRING,\r\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\r\n },\r\n value: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\r\n },\r\n type: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\r\n },\r\n\r\n // icon\r\n name: {\r\n type: Type.STRING,\r\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\r\n },\r\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\r\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\r\n strokeWidth: {\r\n type: Type.NUMBER,\r\n description: \"For 'icon': stroke width.\",\r\n },\r\n },\r\n};\r\n\r\n// NOTE: Gemini tool `parameters` schemas reject `$ref`, so true recursion isn't available here.\r\n// We unroll nesting to a reasonable max depth; for deeper trees, insert in multiple steps.\r\nconst buildBuilderElementSchema = (depth: number): any => {\r\n return {\r\n type: Type.OBJECT,\r\n properties: {\r\n type: {\r\n type: Type.STRING,\r\n enum: ELEMENT_TYPES,\r\n description:\r\n \"Element type to render. 'text' renders a <p>, 'image' renders an <img>, 'link' renders an <a>, 'icon' renders a Lucide icon, 'fragment' renders children only.\",\r\n },\r\n className: {\r\n type: Type.STRING,\r\n description:\r\n \"Tailwind CSS className applied to the rendered element (Tailwind only).\",\r\n },\r\n visible: {\r\n type: Type.BOOLEAN,\r\n description: \"Whether the element should be shown.\",\r\n },\r\n props: BuilderElementPropsSchema,\r\n children: {\r\n type: Type.ARRAY,\r\n description:\r\n \"Nested children. Each child is another element and can itself have children (children[].children[]...).\",\r\n items:\r\n depth > 0\r\n ? buildBuilderElementSchema(depth - 1)\r\n : {\r\n type: Type.OBJECT,\r\n description:\r\n \"Max depth reached in tool schema. If you need deeper nesting, insert the parent first, then insert children using the returned inserted_id as parent_id.\",\r\n },\r\n },\r\n },\r\n required: [\"type\"],\r\n };\r\n};\r\n\r\nexport const BuilderElementSchema: any = buildBuilderElementSchema(6);\r\n\r\nexport const InsertElementSchema = {\r\n name: \"insert_element\",\r\n description:\r\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\r\n parameters: {\r\n type: Type.OBJECT,\r\n properties: {\r\n route: {\r\n type: Type.STRING,\r\n description:\r\n \"The route to insert the element at. Example. '/' or '/about' etc.\",\r\n },\r\n parent_id: {\r\n type: Type.STRING,\r\n description: \"The parent id to insert the element at.\",\r\n },\r\n element: {\r\n ...BuilderElementSchema,\r\n description: \"The element to insert.\",\r\n },\r\n },\r\n required: [\"route\", \"parent_id\", \"element\"],\r\n },\r\n};\r\n"]}
1
+ {"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const ELEMENT_TYPES = [\r\n \"fragment\",\r\n \"div\",\r\n \"text\",\r\n \"image\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"link\",\r\n \"icon\",\r\n] as const;\r\n\r\nconst OnClickActionSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n kind: {\r\n type: Type.STRING,\r\n enum: [\"route\", \"back\", \"reload\", \"external\"],\r\n description:\r\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description:\r\n \"URL to navigate to (used for kind='route' and kind='external').\",\r\n },\r\n replace: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='route': replace history instead of pushing.\",\r\n },\r\n newTab: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='external': open link in a new tab.\",\r\n },\r\n },\r\n required: [\"kind\"],\r\n};\r\n\r\nconst BuilderElementPropsSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n onClick: OnClickActionSchema,\r\n text: {\r\n type: Type.STRING,\r\n description:\r\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description: \"For 'link': the href attribute (defaults to '#').\",\r\n },\r\n placeholder: {\r\n type: Type.STRING,\r\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\r\n },\r\n alt: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\r\n },\r\n target: {\r\n type: Type.STRING,\r\n description: \"For 'link': target attribute (e.g. '_blank').\",\r\n },\r\n rel: {\r\n type: Type.STRING,\r\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\r\n },\r\n value: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\r\n },\r\n type: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\r\n },\r\n\r\n // icon\r\n name: {\r\n type: Type.STRING,\r\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\r\n },\r\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\r\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\r\n strokeWidth: {\r\n type: Type.NUMBER,\r\n description: \"For 'icon': stroke width.\",\r\n },\r\n },\r\n};\r\n\r\n// NOTE: Gemini tool `parameters` schemas reject `$ref`, so true recursion isn't available here.\r\n// We unroll nesting to a reasonable max depth; for deeper trees, insert in multiple steps.\r\nconst buildBuilderElementSchema = (depth: number): any => {\r\n return {\r\n type: Type.OBJECT,\r\n properties: {\r\n type: {\r\n type: Type.STRING,\r\n enum: ELEMENT_TYPES,\r\n description:\r\n \"Element type to render. Use 'text' for <p>, 'image' forn <img>, 'link' for <a>, 'icon' for Lucide icon, 'fragment' renders children only\",\r\n },\r\n className: {\r\n type: Type.STRING,\r\n description: \"Tailwind CSS className (Tailwind only)\",\r\n },\r\n visible: {\r\n type: Type.BOOLEAN,\r\n description: \"Visibility flag\",\r\n },\r\n props: BuilderElementPropsSchema,\r\n children: {\r\n type: Type.ARRAY,\r\n description:\r\n \"Child elements. Each child can itself have children (children[].children[]...)\",\r\n items:\r\n depth > 0\r\n ? buildBuilderElementSchema(depth - 1)\r\n : {\r\n type: Type.OBJECT,\r\n description:\r\n \"Max depth reached. Insert deeper children separately using the returned inserted_id as parent_id\",\r\n },\r\n },\r\n },\r\n required: [\"type\"],\r\n };\r\n};\r\n\r\nexport const BuilderElementSchema: any = buildBuilderElementSchema(4);\r\n\r\nexport const InsertElementSchema = {\r\n name: \"insert_element\",\r\n description:\r\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\r\n parameters: {\r\n type: Type.OBJECT,\r\n properties: {\r\n route: {\r\n type: Type.STRING,\r\n description:\r\n \"The route to insert the element at. Example. '/' or '/about' etc.\",\r\n },\r\n parent_id: {\r\n type: Type.STRING,\r\n description: \"The parent id to insert the element at.\",\r\n },\r\n element: {\r\n ...BuilderElementSchema,\r\n description: \"The element to insert.\",\r\n },\r\n },\r\n required: [\"route\", \"parent_id\", \"element\"],\r\n },\r\n};\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"unsplash.service.d.ts","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAMF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,QAcnD;AAoBD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4E/B;AAED,eAAO,MAAM,8BAA8B,GACzC,IAAI,cAAc,EAClB,KAAK,MAAM,KACV,OAAO,CAAC,IAAI,CAmBd,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,IAAI,cAAc,KACjB,OAAO,CAAC,IAAI,CAcd,CAAC"}
1
+ {"version":3,"file":"unsplash.service.d.ts","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAMF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,QAcnD;AAoBD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA6E/B;AAED,eAAO,MAAM,8BAA8B,GACzC,IAAI,cAAc,EAClB,KAAK,MAAM,KACV,OAAO,CAAC,IAAI,CAmBd,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,IAAI,cAAc,KACjB,OAAO,CAAC,IAAI,CAcd,CAAC"}
@@ -26,6 +26,7 @@ function scoreImage(photo) {
26
26
  return score;
27
27
  }
28
28
  export async function searchUnsplashImage(imgQuery) {
29
+ console.log("searchUnsplashImage", imgQuery);
29
30
  const cfg = unsplashConfig;
30
31
  if (!cfg)
31
32
  throw new Error("Unsplash not configured");
@@ -1 +1 @@
1
- {"version":3,"file":"unsplash.service.js","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"crypto\";\r\nimport { BuilderElement } from \"../types/elements.js\";\r\n\r\nexport interface ResolvedImage {\r\n id: string;\r\n alt: string;\r\n imageUrl: string;\r\n thumbUrl: string;\r\n photographer: string;\r\n photographerUrl: string;\r\n unsplashUrl: string;\r\n width: number;\r\n height: number;\r\n}\r\n\r\ntype UnsplashConfig = {\r\n url: string;\r\n accessKey: string;\r\n};\r\n\r\nlet unsplashConfig: UnsplashConfig | null = null;\r\n\r\nconst cache = new Map<string, ResolvedImage>();\r\n\r\nexport function initUnsplash(\r\n config: Partial<UnsplashConfig> | null | undefined,\r\n) {\r\n const url = String(config?.url ?? \"\").trim();\r\n const accessKey = String(config?.accessKey ?? \"\").trim();\r\n\r\n if (!url || !accessKey) {\r\n unsplashConfig = null;\r\n return;\r\n }\r\n\r\n unsplashConfig = {\r\n url: url.replace(/\\/+$/, \"\"),\r\n accessKey,\r\n };\r\n}\r\n\r\nfunction hashIntent(imgQuery: string) {\r\n return crypto.createHash(\"sha256\").update(imgQuery).digest(\"hex\");\r\n}\r\n\r\nfunction scoreImage(photo: any) {\r\n let score = 0;\r\n\r\n score += (photo.likes || 0) * 0.3;\r\n\r\n if (photo.width > photo.height) {\r\n score += 50;\r\n }\r\n\r\n score += (photo.user.total_photos || 0) * 0.05;\r\n\r\n return score;\r\n}\r\n\r\nexport async function searchUnsplashImage(\r\n imgQuery: string,\r\n): Promise<ResolvedImage | null> {\r\n const cfg = unsplashConfig;\r\n if (!cfg) throw new Error(\"Unsplash not configured\");\r\n\r\n const cacheKey = hashIntent(imgQuery);\r\n\r\n const cached = cache.get(cacheKey);\r\n\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const params = new URLSearchParams({\r\n imgQuery,\r\n per_page: \"10\",\r\n });\r\n\r\n const response = await fetch(\r\n `${cfg.url}/search/photos?${params.toString()}`,\r\n {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n },\r\n );\r\n\r\n if (!response.ok) {\r\n throw new Error(`Unsplash API failed: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n\r\n const photos = data.results;\r\n\r\n if (!photos.length) {\r\n return null;\r\n }\r\n\r\n const ranked = [...photos].sort((a, b) => {\r\n return scoreImage(b) - scoreImage(a);\r\n });\r\n\r\n const top3 = ranked.slice(0, 3);\r\n\r\n const selected = top3[Math.floor(Math.random() * top3.length)];\r\n\r\n // IMPORTANT:\r\n // Required by Unsplash API terms\r\n // Tracks image download usage\r\n if (selected.links.download_location) {\r\n await fetch(selected.links.download_location, {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n });\r\n }\r\n\r\n const resolved: ResolvedImage = {\r\n id: selected.id,\r\n alt: imgQuery,\r\n\r\n imageUrl: selected.urls.regular,\r\n thumbUrl: selected.urls.small,\r\n\r\n photographer: selected.user.name,\r\n photographerUrl: selected.user.links.html,\r\n\r\n unsplashUrl: selected.links.html,\r\n\r\n width: selected.width,\r\n height: selected.height,\r\n };\r\n\r\n cache.set(cacheKey, resolved);\r\n\r\n return resolved;\r\n}\r\n\r\nexport const resolveUnsplashImageForElement = async (\r\n el: BuilderElement,\r\n alt: string,\r\n): Promise<void> => {\r\n if (!unsplashConfig) return;\r\n const query = String(alt ?? \"\").trim();\r\n if (!query) return;\r\n if (el.props?.src) {\r\n console.log(\"src already exists, skipping\");\r\n return;\r\n }\r\n try {\r\n const resolved = await searchUnsplashImage(query);\r\n if (!resolved?.imageUrl) return;\r\n\r\n const anyEl = el as any;\r\n if (!anyEl.props || typeof anyEl.props !== \"object\") anyEl.props = {};\r\n anyEl.props.src = resolved.imageUrl;\r\n anyEl.props.alt = query;\r\n } catch {\r\n // Ignore Unsplash lookup errors and still allow prop updates.\r\n }\r\n};\r\n\r\nexport const resolveUnsplashImagesDeep = async (\r\n el: BuilderElement,\r\n): Promise<void> => {\r\n const anyEl = el as any;\r\n\r\n if (anyEl?.type === \"image\") {\r\n const alt = String(anyEl?.props?.alt ?? \"\").trim();\r\n resolveUnsplashImageForElement(el, alt);\r\n }\r\n\r\n const kids = anyEl?.children;\r\n if (Array.isArray(kids)) {\r\n for (const child of kids) {\r\n await resolveUnsplashImagesDeep(child);\r\n }\r\n }\r\n};\r\n"]}
1
+ {"version":3,"file":"unsplash.service.js","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"crypto\";\r\nimport { BuilderElement } from \"../types/elements.js\";\r\n\r\nexport interface ResolvedImage {\r\n id: string;\r\n alt: string;\r\n imageUrl: string;\r\n thumbUrl: string;\r\n photographer: string;\r\n photographerUrl: string;\r\n unsplashUrl: string;\r\n width: number;\r\n height: number;\r\n}\r\n\r\ntype UnsplashConfig = {\r\n url: string;\r\n accessKey: string;\r\n};\r\n\r\nlet unsplashConfig: UnsplashConfig | null = null;\r\n\r\nconst cache = new Map<string, ResolvedImage>();\r\n\r\nexport function initUnsplash(\r\n config: Partial<UnsplashConfig> | null | undefined,\r\n) {\r\n const url = String(config?.url ?? \"\").trim();\r\n const accessKey = String(config?.accessKey ?? \"\").trim();\r\n\r\n if (!url || !accessKey) {\r\n unsplashConfig = null;\r\n return;\r\n }\r\n\r\n unsplashConfig = {\r\n url: url.replace(/\\/+$/, \"\"),\r\n accessKey,\r\n };\r\n}\r\n\r\nfunction hashIntent(imgQuery: string) {\r\n return crypto.createHash(\"sha256\").update(imgQuery).digest(\"hex\");\r\n}\r\n\r\nfunction scoreImage(photo: any) {\r\n let score = 0;\r\n\r\n score += (photo.likes || 0) * 0.3;\r\n\r\n if (photo.width > photo.height) {\r\n score += 50;\r\n }\r\n\r\n score += (photo.user.total_photos || 0) * 0.05;\r\n\r\n return score;\r\n}\r\n\r\nexport async function searchUnsplashImage(\r\n imgQuery: string,\r\n): Promise<ResolvedImage | null> {\r\n console.log(\"searchUnsplashImage\", imgQuery);\r\n const cfg = unsplashConfig;\r\n if (!cfg) throw new Error(\"Unsplash not configured\");\r\n\r\n const cacheKey = hashIntent(imgQuery);\r\n\r\n const cached = cache.get(cacheKey);\r\n\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const params = new URLSearchParams({\r\n imgQuery,\r\n per_page: \"10\",\r\n });\r\n\r\n const response = await fetch(\r\n `${cfg.url}/search/photos?${params.toString()}`,\r\n {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n },\r\n );\r\n\r\n if (!response.ok) {\r\n throw new Error(`Unsplash API failed: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n\r\n const photos = data.results;\r\n\r\n if (!photos.length) {\r\n return null;\r\n }\r\n\r\n const ranked = [...photos].sort((a, b) => {\r\n return scoreImage(b) - scoreImage(a);\r\n });\r\n\r\n const top3 = ranked.slice(0, 3);\r\n\r\n const selected = top3[Math.floor(Math.random() * top3.length)];\r\n\r\n // IMPORTANT:\r\n // Required by Unsplash API terms\r\n // Tracks image download usage\r\n if (selected.links.download_location) {\r\n await fetch(selected.links.download_location, {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n });\r\n }\r\n\r\n const resolved: ResolvedImage = {\r\n id: selected.id,\r\n alt: imgQuery,\r\n\r\n imageUrl: selected.urls.regular,\r\n thumbUrl: selected.urls.small,\r\n\r\n photographer: selected.user.name,\r\n photographerUrl: selected.user.links.html,\r\n\r\n unsplashUrl: selected.links.html,\r\n\r\n width: selected.width,\r\n height: selected.height,\r\n };\r\n\r\n cache.set(cacheKey, resolved);\r\n\r\n return resolved;\r\n}\r\n\r\nexport const resolveUnsplashImageForElement = async (\r\n el: BuilderElement,\r\n alt: string,\r\n): Promise<void> => {\r\n if (!unsplashConfig) return;\r\n const query = String(alt ?? \"\").trim();\r\n if (!query) return;\r\n if (el.props?.src) {\r\n console.log(\"src already exists, skipping\");\r\n return;\r\n }\r\n try {\r\n const resolved = await searchUnsplashImage(query);\r\n if (!resolved?.imageUrl) return;\r\n\r\n const anyEl = el as any;\r\n if (!anyEl.props || typeof anyEl.props !== \"object\") anyEl.props = {};\r\n anyEl.props.src = resolved.imageUrl;\r\n anyEl.props.alt = query;\r\n } catch {\r\n // Ignore Unsplash lookup errors and still allow prop updates.\r\n }\r\n};\r\n\r\nexport const resolveUnsplashImagesDeep = async (\r\n el: BuilderElement,\r\n): Promise<void> => {\r\n const anyEl = el as any;\r\n\r\n if (anyEl?.type === \"image\") {\r\n const alt = String(anyEl?.props?.alt ?? \"\").trim();\r\n resolveUnsplashImageForElement(el, alt);\r\n }\r\n\r\n const kids = anyEl?.children;\r\n if (Array.isArray(kids)) {\r\n for (const child of kids) {\r\n await resolveUnsplashImagesDeep(child);\r\n }\r\n }\r\n};\r\n"]}
@@ -20,40 +20,33 @@ export declare const projectConfigs: {
20
20
  readonly testing: "none";
21
21
  };
22
22
  readonly renderingConfig: {
23
- readonly approach: "config-driven UI rendering";
24
- readonly routeConventions: {
25
- readonly model: "Routes mean URL paths (e.g. /about, /pricing) in a Next.js App Router app. Each URL route is implemented by a route folder under /app (e.g. app/about) and is driven by a colocated JSON config file.";
26
- readonly definition: "In this repo, \"route\" always refers to the user-facing browser URL pathname, not an arbitrary file path.";
27
- readonly examples: {
28
- readonly urlRoutes: readonly ["/", "/about", "/pricing"];
29
- readonly appRouterFolders: readonly ["app/page.tsx", "app/about/page.tsx", "app/pricing/page.tsx"];
23
+ readonly approach: "config-driven";
24
+ readonly routes: {
25
+ readonly meaning: "URL pathname, not file path";
26
+ readonly examples: readonly ["/", "/about", "/pricing"];
27
+ readonly structure: {
28
+ readonly "/": "app/page.tsx + app/pageConfig.json";
29
+ readonly "/about": "app/about/page.tsx + app/about/pageConfig.json";
30
30
  };
31
- readonly filesPerRoute: readonly ["page.tsx", "pageConfig.json"];
32
- readonly sourceOfTruth: "pageConfig.json (edit this; page.tsx is a fixed renderer)";
33
- readonly configShape: {
34
- readonly file: "pageConfig.json";
35
- readonly root: {
36
- readonly elements: "BuilderElement[]";
37
- };
38
- readonly note: "The page renders config.elements (array of BuilderElement).";
31
+ readonly files: readonly ["page.tsx", "pageConfig.json"];
32
+ readonly sourceOfTruth: "pageConfig.json";
33
+ readonly config: {
34
+ readonly root: "elements: BuilderElement[]";
39
35
  };
40
- readonly locationNote: "These files live inside the route folder (App Router convention). Example: for /about -> app/about/page.tsx and app/about/pageConfig.json.";
41
36
  };
42
- readonly pageRenderer: {
43
- readonly fileName: "page.tsx";
44
- readonly behavior: readonly ["Imports pageConfig from ./pageConfig.json", "Casts config to { elements: BuilderElement[] }", "Renders: config.elements.map(el => <RenderElement key={el.id} el={el} />)"];
45
- readonly canonicalSource: "import { RenderElement } from \"@/lib/renderer/RenderElement\";\nimport pageConfig from \"./pageConfig.json\";\nimport type { BuilderElement } from \"@/types/elements\";\n\nexport default function Page() {\n const config = pageConfig as { elements: BuilderElement[] };\n return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\n}";
37
+ readonly renderer: {
38
+ readonly file: "page.tsx";
39
+ readonly behavior: readonly ["imports ./pageConfig.json", "casts to { elements: BuilderElement[] }", "renders config.elements with RenderElement"];
40
+ readonly fixed: true;
46
41
  };
47
42
  readonly elements: {
48
- readonly typeName: "BuilderElement";
49
- readonly supportedTypes: readonly ["fragment", "div", "text", "image", "button", "input", "textarea", "link", "icon"];
50
- readonly rendering: {
51
- readonly notes: readonly ["Unknown element types are warned and rendered as an error box.", "Elements support Tailwind-only styling via className.", "Elements may have children: BuilderElement[]."];
52
- };
43
+ readonly type: "BuilderElement";
44
+ readonly supported: readonly ["fragment", "div", "text", "image", "button", "input", "textarea", "link", "icon"];
45
+ readonly rules: readonly ["Tailwind via className only", "supports children: BuilderElement[]", "unknown types render error UI"];
53
46
  };
54
- readonly generatorGuidance: {
55
- readonly do: readonly ["Treat a route as a URL path (e.g. /about). Its code lives in the corresponding Next.js App Router folder (e.g. app/about).", "UI changes can happen only by editing that route folder's pageConfig.json elements tree.", "@/lib/renderer/RenderElement , @/types/elements already exist. No need to create them.", "When creating a new URL route (e.g. /pricing), create the App Router folder (e.g. app/pricing) with page.tsx (fixed renderer) + pageConfig.json (initial elements). After that, codegen should only modify pageConfig.json.", "Use Tailwind in className; prefer composition via nested children."];
56
- readonly dont: readonly ["Do not confuse URL routes with file paths; do not invent 'routes' that are just filenames.", "Do not change page.tsx structure for URL routes (it is a fixed renderer).", "Do not generate React components for layout; encode structure in JSON elements."];
47
+ readonly guidance: {
48
+ readonly do: readonly ["route = URL path", "edit only pageConfig.json for UI changes", "keep '/' populated", "RenderElement and BuilderElement already exist", "new routes require page.tsx + pageConfig.json", "prefer nested composition"];
49
+ readonly dont: readonly ["don't treat routes as file paths", "don't modify page.tsx", "don't generate React layout components"];
57
50
  };
58
51
  };
59
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"configs.constants.d.ts","sourceRoot":"","sources":["../../../src/indexer/data/configs.constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Fc,CAAC;AAE1C,eAAO,MAAM,QAAQ;;;;;;CAyBc,CAAC"}
1
+ {"version":3,"file":"configs.constants.d.ts","sourceRoot":"","sources":["../../../src/indexer/data/configs.constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Fc,CAAC;AAE1C,eAAO,MAAM,QAAQ;;;;;;CAyBc,CAAC"}
@@ -20,42 +20,32 @@ export const projectConfigs = {
20
20
  testing: "none",
21
21
  },
22
22
  renderingConfig: {
23
- approach: "config-driven UI rendering",
24
- routeConventions: {
25
- model: "Routes mean URL paths (e.g. /about, /pricing) in a Next.js App Router app. Each URL route is implemented by a route folder under /app (e.g. app/about) and is driven by a colocated JSON config file.",
26
- definition: 'In this repo, "route" always refers to the user-facing browser URL pathname, not an arbitrary file path.',
27
- examples: {
28
- urlRoutes: ["/", "/about", "/pricing"],
29
- appRouterFolders: ["app/page.tsx", "app/about/page.tsx", "app/pricing/page.tsx"],
23
+ approach: "config-driven",
24
+ routes: {
25
+ meaning: "URL pathname, not file path",
26
+ examples: ["/", "/about", "/pricing"],
27
+ structure: {
28
+ "/": "app/page.tsx + app/pageConfig.json",
29
+ "/about": "app/about/page.tsx + app/about/pageConfig.json",
30
30
  },
31
- filesPerRoute: ["page.tsx", "pageConfig.json"],
32
- sourceOfTruth: "pageConfig.json (edit this; page.tsx is a fixed renderer)",
33
- configShape: {
34
- file: "pageConfig.json",
35
- root: { elements: "BuilderElement[]" },
36
- note: "The page renders config.elements (array of BuilderElement).",
31
+ files: ["page.tsx", "pageConfig.json"],
32
+ sourceOfTruth: "pageConfig.json",
33
+ config: {
34
+ root: "elements: BuilderElement[]",
37
35
  },
38
- locationNote: "These files live inside the route folder (App Router convention). Example: for /about -> app/about/page.tsx and app/about/pageConfig.json.",
39
36
  },
40
- pageRenderer: {
41
- fileName: "page.tsx",
37
+ renderer: {
38
+ file: "page.tsx",
42
39
  behavior: [
43
- "Imports pageConfig from ./pageConfig.json",
44
- "Casts config to { elements: BuilderElement[] }",
45
- "Renders: config.elements.map(el => <RenderElement key={el.id} el={el} />)",
40
+ "imports ./pageConfig.json",
41
+ "casts to { elements: BuilderElement[] }",
42
+ "renders config.elements with RenderElement",
46
43
  ],
47
- canonicalSource: `import { RenderElement } from "@/lib/renderer/RenderElement";
48
- import pageConfig from "./pageConfig.json";
49
- import type { BuilderElement } from "@/types/elements";
50
-
51
- export default function Page() {
52
- const config = pageConfig as { elements: BuilderElement[] };
53
- return config.elements.map((el) => <RenderElement key={el.id} el={el} />);
54
- }`,
44
+ fixed: true,
55
45
  },
56
46
  elements: {
57
- typeName: "BuilderElement",
58
- supportedTypes: [
47
+ type: "BuilderElement",
48
+ supported: [
59
49
  "fragment",
60
50
  "div",
61
51
  "text",
@@ -66,26 +56,25 @@ export default function Page() {
66
56
  "link",
67
57
  "icon",
68
58
  ],
69
- rendering: {
70
- notes: [
71
- "Unknown element types are warned and rendered as an error box.",
72
- "Elements support Tailwind-only styling via className.",
73
- "Elements may have children: BuilderElement[].",
74
- ],
75
- },
59
+ rules: [
60
+ "Tailwind via className only",
61
+ "supports children: BuilderElement[]",
62
+ "unknown types render error UI",
63
+ ],
76
64
  },
77
- generatorGuidance: {
65
+ guidance: {
78
66
  do: [
79
- "Treat a route as a URL path (e.g. /about). Its code lives in the corresponding Next.js App Router folder (e.g. app/about).",
80
- "UI changes can happen only by editing that route folder's pageConfig.json elements tree.",
81
- "@/lib/renderer/RenderElement , @/types/elements already exist. No need to create them.",
82
- "When creating a new URL route (e.g. /pricing), create the App Router folder (e.g. app/pricing) with page.tsx (fixed renderer) + pageConfig.json (initial elements). After that, codegen should only modify pageConfig.json.",
83
- "Use Tailwind in className; prefer composition via nested children.",
67
+ "route = URL path",
68
+ "edit only pageConfig.json for UI changes",
69
+ "keep '/' populated",
70
+ "RenderElement and BuilderElement already exist",
71
+ "new routes require page.tsx + pageConfig.json",
72
+ "prefer nested composition",
84
73
  ],
85
74
  dont: [
86
- "Do not confuse URL routes with file paths; do not invent 'routes' that are just filenames.",
87
- "Do not change page.tsx structure for URL routes (it is a fixed renderer).",
88
- "Do not generate React components for layout; encode structure in JSON elements.",
75
+ "don't treat routes as file paths",
76
+ "don't modify page.tsx",
77
+ "don't generate React layout components",
89
78
  ],
90
79
  },
91
80
  },
@@ -1 +1 @@
1
- {"version":3,"file":"configs.constants.js","sourceRoot":"","sources":["../../../src/indexer/data/configs.constants.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe,EAAE;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,YAAY;QACtB,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,cAAc;KACxB;IACD,aAAa,EAAE;QACb,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,UAAU;QACzB,SAAS,EAAE,UAAU;QACrB,YAAY,EAAE,+BAA+B;KAC9C;IACD,aAAa,EAAE;QACb,cAAc,EAAE,KAAK;QACrB,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,cAAc;QACzB,OAAO,EAAE,MAAM;KAChB;IACD,eAAe,EAAE;QACf,QAAQ,EAAE,4BAA4B;QACtC,gBAAgB,EAAE;YAChB,KAAK,EACH,uMAAuM;YACzM,UAAU,EACR,0GAA0G;YAC5G,QAAQ,EAAE;gBACR,SAAS,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC;gBACtC,gBAAgB,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,sBAAsB,CAAC;aACjF;YACD,aAAa,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC;YAC9C,aAAa,EACX,2DAA2D;YAC7D,WAAW,EAAE;gBACX,IAAI,EAAE,iBAAiB;gBACvB,IAAI,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;gBACtC,IAAI,EAAE,6DAA6D;aACpE;YACD,YAAY,EACV,4IAA4I;SAC/I;QACD,YAAY,EAAE;YACZ,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE;gBACR,2CAA2C;gBAC3C,gDAAgD;gBAChD,2EAA2E;aAC5E;YACD,eAAe,EAAE;;;;;;;EAOrB;SACG;QACD,QAAQ,EAAE;YACR,QAAQ,EAAE,gBAAgB;YAC1B,cAAc,EAAE;gBACd,UAAU;gBACV,KAAK;gBACL,MAAM;gBACN,OAAO;gBACP,QAAQ;gBACR,OAAO;gBACP,UAAU;gBACV,MAAM;gBACN,MAAM;aACP;YACD,SAAS,EAAE;gBACT,KAAK,EAAE;oBACL,gEAAgE;oBAChE,uDAAuD;oBACvD,+CAA+C;iBAChD;aACF;SACF;QACD,iBAAiB,EAAE;YACjB,EAAE,EAAE;gBACF,4HAA4H;gBAC5H,0FAA0F;gBAC1F,wFAAwF;gBACxF,6NAA6N;gBAC7N,oEAAoE;aACrE;YACD,IAAI,EAAE;gBACJ,4FAA4F;gBAC5F,2EAA2E;gBAC3E,iFAAiF;aAClF;SACF;KACF;CACsC,CAAC;AAE1C,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,iBAAiB,EAAE;QACjB,KAAK;QACL,MAAM;QACN,KAAK;QACL,MAAM;QACN,OAAO;QACP,KAAK;QACL,MAAM;QACN,MAAM;QACN,OAAO;QACP,OAAO;KACR;IACD,kBAAkB,EAAE;QAClB,cAAc;QACd,OAAO;QACP,MAAM;QACN,OAAO;QACP,KAAK;QACL,UAAU;QACV,MAAM;KACP;IACD,YAAY,EAAE,MAAO;IACrB,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,GAAG;CACgB,CAAC","sourcesContent":["import { ProjectConfigsConfig } from \"../../types/index/configs.types.js\";\nimport { IndexingConfig } from \"../../types/index/indexing.types.js\";\n\nexport const projectConfigs = {\n frameworkConfig: {\n name: \"Next.js\",\n router: \"App Router\",\n language: \"TypeScript\",\n icons: \"lucide-react icons\",\n styling: \"Tailwind CSS\",\n },\n runtimeConfig: {\n target: \"frontend-only\",\n serverActions: \"disabled\",\n apiRoutes: \"disabled\",\n dataFetching: \"client-side (fetch or mocked)\",\n },\n toolingConfig: {\n packageManager: \"npm\",\n linting: \"eslint\",\n formatting: \"prettier\",\n typecheck: \"tsc --noEmit\",\n testing: \"none\",\n },\n renderingConfig: {\n approach: \"config-driven UI rendering\",\n routeConventions: {\n model:\n \"Routes mean URL paths (e.g. /about, /pricing) in a Next.js App Router app. Each URL route is implemented by a route folder under /app (e.g. app/about) and is driven by a colocated JSON config file.\",\n definition:\n 'In this repo, \"route\" always refers to the user-facing browser URL pathname, not an arbitrary file path.',\n examples: {\n urlRoutes: [\"/\", \"/about\", \"/pricing\"],\n appRouterFolders: [\"app/page.tsx\", \"app/about/page.tsx\", \"app/pricing/page.tsx\"],\n },\n filesPerRoute: [\"page.tsx\", \"pageConfig.json\"],\n sourceOfTruth:\n \"pageConfig.json (edit this; page.tsx is a fixed renderer)\",\n configShape: {\n file: \"pageConfig.json\",\n root: { elements: \"BuilderElement[]\" },\n note: \"The page renders config.elements (array of BuilderElement).\",\n },\n locationNote:\n \"These files live inside the route folder (App Router convention). Example: for /about -> app/about/page.tsx and app/about/pageConfig.json.\",\n },\n pageRenderer: {\n fileName: \"page.tsx\",\n behavior: [\n \"Imports pageConfig from ./pageConfig.json\",\n \"Casts config to { elements: BuilderElement[] }\",\n \"Renders: config.elements.map(el => <RenderElement key={el.id} el={el} />)\",\n ],\n canonicalSource: `import { RenderElement } from \"@/lib/renderer/RenderElement\";\nimport pageConfig from \"./pageConfig.json\";\nimport type { BuilderElement } from \"@/types/elements\";\n\nexport default function Page() {\n const config = pageConfig as { elements: BuilderElement[] };\n return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\n}`,\n },\n elements: {\n typeName: \"BuilderElement\",\n supportedTypes: [\n \"fragment\",\n \"div\",\n \"text\",\n \"image\",\n \"button\",\n \"input\",\n \"textarea\",\n \"link\",\n \"icon\",\n ],\n rendering: {\n notes: [\n \"Unknown element types are warned and rendered as an error box.\",\n \"Elements support Tailwind-only styling via className.\",\n \"Elements may have children: BuilderElement[].\",\n ],\n },\n },\n generatorGuidance: {\n do: [\n \"Treat a route as a URL path (e.g. /about). Its code lives in the corresponding Next.js App Router folder (e.g. app/about).\",\n \"UI changes can happen only by editing that route folder's pageConfig.json elements tree.\",\n \"@/lib/renderer/RenderElement , @/types/elements already exist. No need to create them.\",\n \"When creating a new URL route (e.g. /pricing), create the App Router folder (e.g. app/pricing) with page.tsx (fixed renderer) + pageConfig.json (initial elements). After that, codegen should only modify pageConfig.json.\",\n \"Use Tailwind in className; prefer composition via nested children.\",\n ],\n dont: [\n \"Do not confuse URL routes with file paths; do not invent 'routes' that are just filenames.\",\n \"Do not change page.tsx structure for URL routes (it is a fixed renderer).\",\n \"Do not generate React components for layout; encode structure in JSON elements.\",\n ],\n },\n },\n} as const satisfies ProjectConfigsConfig;\n\nexport const indexing = {\n includeExtensions: [\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".md\",\n \".mdx\",\n \".css\",\n \".scss\",\n \".sass\",\n ],\n excludeDirectories: [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n \"out\",\n \"coverage\",\n \".git\",\n ],\n maxFileBytes: 200_000,\n chunkSize: 900,\n chunkOverlap: 150,\n} as const satisfies IndexingConfig;\n"]}
1
+ {"version":3,"file":"configs.constants.js","sourceRoot":"","sources":["../../../src/indexer/data/configs.constants.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe,EAAE;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,YAAY;QACtB,KAAK,EAAE,oBAAoB;QAC3B,OAAO,EAAE,cAAc;KACxB;IACD,aAAa,EAAE;QACb,MAAM,EAAE,eAAe;QACvB,aAAa,EAAE,UAAU;QACzB,SAAS,EAAE,UAAU;QACrB,YAAY,EAAE,+BAA+B;KAC9C;IACD,aAAa,EAAE;QACb,cAAc,EAAE,KAAK;QACrB,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,cAAc;QACzB,OAAO,EAAE,MAAM;KAChB;IACD,eAAe,EAAE;QACf,QAAQ,EAAE,eAAe;QAEzB,MAAM,EAAE;YACN,OAAO,EAAE,6BAA6B;YACtC,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC;YAErC,SAAS,EAAE;gBACT,GAAG,EAAE,oCAAoC;gBACzC,QAAQ,EAAE,gDAAgD;aAC3D;YAED,KAAK,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC;YAEtC,aAAa,EAAE,iBAAiB;YAEhC,MAAM,EAAE;gBACN,IAAI,EAAE,4BAA4B;aACnC;SACF;QAED,QAAQ,EAAE;YACR,IAAI,EAAE,UAAU;YAEhB,QAAQ,EAAE;gBACR,2BAA2B;gBAC3B,yCAAyC;gBACzC,4CAA4C;aAC7C;YAED,KAAK,EAAE,IAAI;SACZ;QAED,QAAQ,EAAE;YACR,IAAI,EAAE,gBAAgB;YAEtB,SAAS,EAAE;gBACT,UAAU;gBACV,KAAK;gBACL,MAAM;gBACN,OAAO;gBACP,QAAQ;gBACR,OAAO;gBACP,UAAU;gBACV,MAAM;gBACN,MAAM;aACP;YAED,KAAK,EAAE;gBACL,6BAA6B;gBAC7B,qCAAqC;gBACrC,+BAA+B;aAChC;SACF;QAED,QAAQ,EAAE;YACR,EAAE,EAAE;gBACF,kBAAkB;gBAClB,0CAA0C;gBAC1C,oBAAoB;gBACpB,gDAAgD;gBAChD,+CAA+C;gBAC/C,2BAA2B;aAC5B;YAED,IAAI,EAAE;gBACJ,kCAAkC;gBAClC,uBAAuB;gBACvB,wCAAwC;aACzC;SACF;KACF;CACsC,CAAC;AAE1C,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,iBAAiB,EAAE;QACjB,KAAK;QACL,MAAM;QACN,KAAK;QACL,MAAM;QACN,OAAO;QACP,KAAK;QACL,MAAM;QACN,MAAM;QACN,OAAO;QACP,OAAO;KACR;IACD,kBAAkB,EAAE;QAClB,cAAc;QACd,OAAO;QACP,MAAM;QACN,OAAO;QACP,KAAK;QACL,UAAU;QACV,MAAM;KACP;IACD,YAAY,EAAE,MAAO;IACrB,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,GAAG;CACgB,CAAC","sourcesContent":["import { ProjectConfigsConfig } from \"../../types/index/configs.types.js\";\nimport { IndexingConfig } from \"../../types/index/indexing.types.js\";\n\nexport const projectConfigs = {\n frameworkConfig: {\n name: \"Next.js\",\n router: \"App Router\",\n language: \"TypeScript\",\n icons: \"lucide-react icons\",\n styling: \"Tailwind CSS\",\n },\n runtimeConfig: {\n target: \"frontend-only\",\n serverActions: \"disabled\",\n apiRoutes: \"disabled\",\n dataFetching: \"client-side (fetch or mocked)\",\n },\n toolingConfig: {\n packageManager: \"npm\",\n linting: \"eslint\",\n formatting: \"prettier\",\n typecheck: \"tsc --noEmit\",\n testing: \"none\",\n },\n renderingConfig: {\n approach: \"config-driven\",\n\n routes: {\n meaning: \"URL pathname, not file path\",\n examples: [\"/\", \"/about\", \"/pricing\"],\n\n structure: {\n \"/\": \"app/page.tsx + app/pageConfig.json\",\n \"/about\": \"app/about/page.tsx + app/about/pageConfig.json\",\n },\n\n files: [\"page.tsx\", \"pageConfig.json\"],\n\n sourceOfTruth: \"pageConfig.json\",\n\n config: {\n root: \"elements: BuilderElement[]\",\n },\n },\n\n renderer: {\n file: \"page.tsx\",\n\n behavior: [\n \"imports ./pageConfig.json\",\n \"casts to { elements: BuilderElement[] }\",\n \"renders config.elements with RenderElement\",\n ],\n\n fixed: true,\n },\n\n elements: {\n type: \"BuilderElement\",\n\n supported: [\n \"fragment\",\n \"div\",\n \"text\",\n \"image\",\n \"button\",\n \"input\",\n \"textarea\",\n \"link\",\n \"icon\",\n ],\n\n rules: [\n \"Tailwind via className only\",\n \"supports children: BuilderElement[]\",\n \"unknown types render error UI\",\n ],\n },\n\n guidance: {\n do: [\n \"route = URL path\",\n \"edit only pageConfig.json for UI changes\",\n \"keep '/' populated\",\n \"RenderElement and BuilderElement already exist\",\n \"new routes require page.tsx + pageConfig.json\",\n \"prefer nested composition\",\n ],\n\n dont: [\n \"don't treat routes as file paths\",\n \"don't modify page.tsx\",\n \"don't generate React layout components\",\n ],\n },\n },\n} as const satisfies ProjectConfigsConfig;\n\nexport const indexing = {\n includeExtensions: [\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".md\",\n \".mdx\",\n \".css\",\n \".scss\",\n \".sass\",\n ],\n excludeDirectories: [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n \"out\",\n \"coverage\",\n \".git\",\n ],\n maxFileBytes: 200_000,\n chunkSize: 900,\n chunkOverlap: 150,\n} as const satisfies IndexingConfig;\n"]}
@@ -1,5 +1,4 @@
1
1
  export type * from "./index/configs.types.js";
2
- export type * from "./index/conventions.types.js";
3
2
  export type * from "./index/index.types.js";
4
3
  export type * from "./index/indexing.types.js";
5
4
  export type * from "./projectInfo.types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AACA,mBAAmB,0BAA0B,CAAC;AAC9C,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,wBAAwB,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AACA,mBAAmB,0BAA0B,CAAC;AAC9C,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,wBAAwB,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AAMA,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC","sourcesContent":["// types/public.ts\r\nexport type * from \"./index/configs.types.js\";\r\nexport type * from \"./index/conventions.types.js\";\r\nexport type * from \"./index/index.types.js\";\r\nexport type * from \"./index/indexing.types.js\";\r\nexport type * from \"./projectInfo.types.js\";\r\nexport * from \"./context.types.js\";\r\nexport * from \"./events.js\";\r\nexport * from \"./updatePlan.types.js\";\r\n"]}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AAKA,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC","sourcesContent":["// types/public.ts\r\nexport type * from \"./index/configs.types.js\";\r\nexport type * from \"./index/index.types.js\";\r\nexport type * from \"./index/indexing.types.js\";\r\nexport type * from \"./projectInfo.types.js\";\r\nexport * from \"./context.types.js\";\r\nexport * from \"./events.js\";\r\nexport * from \"./updatePlan.types.js\";\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedangiitb/qwintly-core",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "Qwintly Core",
5
5
  "homepage": "https://github.com/vedangiitb/qwintly-core#readme",
6
6
  "bugs": {
@@ -1,40 +0,0 @@
1
- export interface ProjectConventionsConfig {
2
- shadcn: ShadcnConventionsConfig;
3
- folderConventions: FolderConventionsConfig;
4
- importsConventions: ImportsConventionsConfig;
5
- routingConventions: RoutingConventionsConfig;
6
- namingConventions: NamingConventionsConfig;
7
- uiArchitecture: UIArchitectureConfig;
8
- }
9
- export interface ShadcnConventionsConfig {
10
- installed: readonly string[];
11
- location: string;
12
- notes: string;
13
- }
14
- export type FolderConventionsConfig = Record<string, string>;
15
- export interface ImportsConventionsConfig {
16
- alias: string;
17
- order: readonly string[];
18
- }
19
- export interface RoutingConventionsConfig {
20
- required: readonly string[];
21
- requiredPerRoute: readonly string[];
22
- optionalPerRoute: readonly string[];
23
- routeGroups: string;
24
- dynamicSegments: string;
25
- }
26
- export interface NamingConventionsConfig {
27
- components: string;
28
- folders: string;
29
- hooks: string;
30
- }
31
- export interface UIArchitectureConfig {
32
- pattern: string;
33
- rule: readonly string[];
34
- configStructure: {
35
- root: string;
36
- elementTypes: Record<string, string>;
37
- rules: readonly string[];
38
- };
39
- }
40
- //# sourceMappingURL=conventions.types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conventions.types.d.ts","sourceRoot":"","sources":["../../../src/types/index/conventions.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,uBAAuB,CAAC;IAChC,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,kBAAkB,EAAE,wBAAwB,CAAC;IAC7C,kBAAkB,EAAE,wBAAwB,CAAC;IAC7C,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,cAAc,EAAE,oBAAoB,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7D,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE;QACf,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;KAC1B,CAAC;CACH"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=conventions.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conventions.types.js","sourceRoot":"","sources":["../../../src/types/index/conventions.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface ProjectConventionsConfig {\n shadcn: ShadcnConventionsConfig;\n folderConventions: FolderConventionsConfig;\n importsConventions: ImportsConventionsConfig;\n routingConventions: RoutingConventionsConfig;\n namingConventions: NamingConventionsConfig;\n uiArchitecture: UIArchitectureConfig;\n}\n\nexport interface ShadcnConventionsConfig {\n installed: readonly string[];\n location: string;\n notes: string;\n}\n\nexport type FolderConventionsConfig = Record<string, string>;\n\nexport interface ImportsConventionsConfig {\n alias: string;\n order: readonly string[];\n}\n\nexport interface RoutingConventionsConfig {\n required: readonly string[];\n requiredPerRoute: readonly string[];\n optionalPerRoute: readonly string[];\n routeGroups: string;\n dynamicSegments: string;\n}\n\nexport interface NamingConventionsConfig {\n components: string;\n folders: string;\n hooks: string;\n}\n\nexport interface UIArchitectureConfig {\n pattern: string;\n rule: readonly string[];\n configStructure: {\n root: string;\n elementTypes: Record<string, string>;\n rules: readonly string[];\n };\n}\n"]}