@vedangiitb/qwintly-core 1.4.2 → 1.4.4

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 (55) hide show
  1. package/dist/ai/prompts/codegen.prompt.d.ts.map +1 -1
  2. package/dist/ai/prompts/codegen.prompt.js +1 -0
  3. package/dist/ai/prompts/codegen.prompt.js.map +1 -1
  4. package/dist/ai/prompts/planner.prompt.d.ts.map +1 -1
  5. package/dist/ai/prompts/planner.prompt.js +1 -0
  6. package/dist/ai/prompts/planner.prompt.js.map +1 -1
  7. package/dist/ai/toolLoop/toolLoopRunner.d.ts.map +1 -1
  8. package/dist/ai/toolLoop/toolLoopRunner.js +13 -0
  9. package/dist/ai/toolLoop/toolLoopRunner.js.map +1 -1
  10. package/dist/ai/tools/helpers/pageConfigJson.helpers.d.ts +13 -0
  11. package/dist/ai/tools/helpers/pageConfigJson.helpers.d.ts.map +1 -1
  12. package/dist/ai/tools/helpers/pageConfigJson.helpers.js +94 -0
  13. package/dist/ai/tools/helpers/pageConfigJson.helpers.js.map +1 -1
  14. package/dist/ai/tools/implementations/createNewRoute.impl.d.ts.map +1 -1
  15. package/dist/ai/tools/implementations/createNewRoute.impl.js +26 -22
  16. package/dist/ai/tools/implementations/createNewRoute.impl.js.map +1 -1
  17. package/dist/ai/tools/implementations/deleteElement.impl.js +2 -2
  18. package/dist/ai/tools/implementations/deleteElement.impl.js.map +1 -1
  19. package/dist/ai/tools/implementations/insertElement.impl.js +2 -2
  20. package/dist/ai/tools/implementations/insertElement.impl.js.map +1 -1
  21. package/dist/ai/tools/implementations/updateClassName.impl.js +2 -2
  22. package/dist/ai/tools/implementations/updateClassName.impl.js.map +1 -1
  23. package/dist/ai/tools/implementations/updateProps.impl.js +2 -2
  24. package/dist/ai/tools/implementations/updateProps.impl.js.map +1 -1
  25. package/dist/ai/tools/schemas/createNewRoute.schema.js +1 -1
  26. package/dist/ai/tools/schemas/createNewRoute.schema.js.map +1 -1
  27. package/dist/ai/tools/schemas/deleteElement.schema.js +1 -1
  28. package/dist/ai/tools/schemas/deleteElement.schema.js.map +1 -1
  29. package/dist/ai/tools/schemas/getAvailableRoutes.schema.d.ts +10 -0
  30. package/dist/ai/tools/schemas/getAvailableRoutes.schema.d.ts.map +1 -0
  31. package/dist/ai/tools/schemas/getAvailableRoutes.schema.js +10 -0
  32. package/dist/ai/tools/schemas/getAvailableRoutes.schema.js.map +1 -0
  33. package/dist/ai/tools/schemas/insertElement.schema.js +1 -1
  34. package/dist/ai/tools/schemas/insertElement.schema.js.map +1 -1
  35. package/dist/ai/tools/schemas/updateClassName.schema.js +1 -1
  36. package/dist/ai/tools/schemas/updateClassName.schema.js.map +1 -1
  37. package/dist/ai/tools/schemas/updateProps.schema.js +1 -1
  38. package/dist/ai/tools/schemas/updateProps.schema.js.map +1 -1
  39. package/dist/ai/tools/toolsets/codegenTools.d.ts.map +1 -1
  40. package/dist/ai/tools/toolsets/codegenTools.js +2 -0
  41. package/dist/ai/tools/toolsets/codegenTools.js.map +1 -1
  42. package/dist/ai/tools/toolsets/plannerTools.d.ts.map +1 -1
  43. package/dist/ai/tools/toolsets/plannerTools.js +2 -0
  44. package/dist/ai/tools/toolsets/plannerTools.js.map +1 -1
  45. package/dist/ai/tools/validators/builderElement.zod.js +2 -2
  46. package/dist/ai/tools/validators/builderElement.zod.js.map +1 -1
  47. package/dist/tests/createNewRoute.impl.test.js +51 -2
  48. package/dist/tests/createNewRoute.impl.test.js.map +1 -1
  49. package/dist/tests/insertUpdate.impl.test.js +93 -0
  50. package/dist/tests/insertUpdate.impl.test.js.map +1 -1
  51. package/dist/tests/toolLoopRunner.routes.test.d.ts +2 -0
  52. package/dist/tests/toolLoopRunner.routes.test.d.ts.map +1 -0
  53. package/dist/tests/toolLoopRunner.routes.test.js +99 -0
  54. package/dist/tests/toolLoopRunner.routes.test.js.map +1 -0
  55. package/package.json +1 -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,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,WA6E5D,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,WA8E5D,CAAC"}
@@ -25,6 +25,7 @@ export const codegenPrompt = (params) => {
25
25
  - delete_element: Delete element
26
26
  - update_classname: Update className
27
27
  - update_props: Update props
28
+ - get_available_routes: Get available routes
28
29
  - submit_codegen_done: Finish task
29
30
 
30
31
  Rules:
@@ -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,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;;;;;;;;;;;;;;;;;;;;;;;;;;MA0BE,CAAC,IAAI,EAAE,CACT,CAAC;IAEH,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 - update_global_styles: Update app/styleConfig.json global design tokens\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 - For any tool arg named route, always use URL paths with forward slashes (e.g. '/', '/pricing'); never use '\\\\' or filesystem paths like 'app/pricing'.\r\n - insert_element supports optional before_id to insert before an existing sibling; if omitted or not found, it appends to the end.\r\n - Include images whenever mentoned to be included. Just use alt tag for images. image src auto-generated from alt\r\n - lucide-react icons only\r\n - Prefer semantic Tailwind tokens (bg-background, text-foreground, border-border, ring-ring, etc.) over hardcoded colors (e.g. slate-*, bg-white) for global styles. If you need different global colors/radius, call update_global_styles first, then use token-based classes.\r\n - update_global_styles args MUST be a flat JSON object with token keys as optional params. Include at least 1 key.\r\n - While updating global styles make sure that the styles updating (ex. background, foreground) are used in the right places (using bg-background, text-foreground, etc.). If not include them by updating the classname using update_classname tool\r\n - Never call update_global_styles with {} (empty object). If you don't need to change styles, do not call this tool.\r\n - Example: {\"radius\":\"0.75rem\",\"background\":\"oklch(0.98 0.01 80)\"}.\r\n\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
+ {"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;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2BE,CAAC,IAAI,EAAE,CACT,CAAC;IAEH,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 - update_global_styles: Update app/styleConfig.json global design tokens\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 - get_available_routes: Get available routes\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 - For any tool arg named route, always use URL paths with forward slashes (e.g. '/', '/pricing'); never use '\\\\' or filesystem paths like 'app/pricing'.\r\n - insert_element supports optional before_id to insert before an existing sibling; if omitted or not found, it appends to the end.\r\n - Include images whenever mentoned to be included. Just use alt tag for images. image src auto-generated from alt\r\n - lucide-react icons only\r\n - Prefer semantic Tailwind tokens (bg-background, text-foreground, border-border, ring-ring, etc.) over hardcoded colors (e.g. slate-*, bg-white) for global styles. If you need different global colors/radius, call update_global_styles first, then use token-based classes.\r\n - update_global_styles args MUST be a flat JSON object with token keys as optional params. Include at least 1 key.\r\n - While updating global styles make sure that the styles updating (ex. background, foreground) are used in the right places (using bg-background, text-foreground, etc.). If not include them by updating the classname using update_classname tool\r\n - Never call update_global_styles with {} (empty object). If you don't need to change styles, do not call this tool.\r\n - Example: {\"radius\":\"0.75rem\",\"background\":\"oklch(0.98 0.01 80)\"}.\r\n\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.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,WAsEzD,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,WAuEzD,CAAC"}
@@ -21,6 +21,7 @@ export const plannerPrompt = (params) => {
21
21
  - read_file: read file
22
22
  - search: search codebase
23
23
  - list_dir: list dirs
24
+ - get_available_routes: Get available routes
24
25
  - submit_planner_tasks: Finalize planner output
25
26
 
26
27
  Styling guidance:
@@ -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,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;;;;;;;;;;;;KAYC,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 Styling guidance:\r\n - Codegen can call update_global_styles to modify app/styleConfig.json (global design tokens).\r\n - Prefer semantic Tailwind token classes (bg-background, text-foreground, border-border, ring-ring, etc.) so global styles are utilized.\r\n - While updating global styles make sure that the styles updating (ex. background, foreground) are used in the right places. If not try including them by updating the classname\r\n - If a task requires changing theme tokens, specify exact update_global_styles args as a flat object: {\"<tokenKey>\":\"<cssString>\"} (never {}).\r\n - Try including images whereever needed in the task description. Also tell what the image should be.\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
+ {"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;;;;;;;;;;;;;KAaC,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 - get_available_routes: Get available routes\r\n - submit_planner_tasks: Finalize planner output\r\n\r\n Styling guidance:\r\n - Codegen can call update_global_styles to modify app/styleConfig.json (global design tokens).\r\n - Prefer semantic Tailwind token classes (bg-background, text-foreground, border-border, ring-ring, etc.) so global styles are utilized.\r\n - While updating global styles make sure that the styles updating (ex. background, foreground) are used in the right places. If not try including them by updating the classname\r\n - If a task requires changing theme tokens, specify exact update_global_styles args as a flat object: {\"<tokenKey>\":\"<cssString>\"} (never {}).\r\n - Try including images whereever needed in the task description. Also tell what the image should be.\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":"toolLoopRunner.d.ts","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAe,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAK/D,OAAO,EAML,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,aAAa,EAAE,GAAG,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,KACE,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE,CAAC;AAEF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAokBzB"}
1
+ {"version":3,"file":"toolLoopRunner.d.ts","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAe,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAM/D,OAAO,EAML,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,aAAa,EAAE,GAAG,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,KACE,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE,CAAC;AAEF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAglBzB"}
@@ -5,6 +5,7 @@ import { EVENT_TYPES } from "../../types/events.js";
5
5
  import { STYLE_TOKEN_KEYS } from "../../types/styleConfig.js";
6
6
  import { createWorkspaceToolImpls } from "../tools/implementations/factories.js";
7
7
  import { parsePlannerTasksUnknown } from "./plannerTaskParser.js";
8
+ import { getAvailableRoutes } from "../tools/helpers/pageConfigJson.helpers.js";
8
9
  import { compactForModel, DEFAULT_CONTEXT_POLICY, normalizeReadFileArgs, redactFunctionCallArgs, } from "./toolLoopContext.js";
9
10
  import { aiCallWithRetry, buildToolStatusMessage, recordToolEvent, serializeError, } from "./toolLoopRunnerUtils.js";
10
11
  export async function runToolLoop(options) {
@@ -65,6 +66,14 @@ export async function runToolLoop(options) {
65
66
  const parent_id = String(args.parent_id ?? "");
66
67
  const element = args.element;
67
68
  const result = await impls.insertElementImpl(route, parent_id, element);
69
+ if (!result.success) {
70
+ const available = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });
71
+ return {
72
+ success: false,
73
+ error: `insert_element failed: ${result.error}. Available routes are: ${JSON.stringify(available)}. If you intend to create a new route, create it using the 'create_new_route' tool.`,
74
+ available_routes: available,
75
+ };
76
+ }
68
77
  return result;
69
78
  },
70
79
  update_props: async (args) => {
@@ -85,6 +94,10 @@ export async function runToolLoop(options) {
85
94
  const result = await impls.updateClassNameImpl(route, element_id, class_name);
86
95
  return result;
87
96
  },
97
+ get_available_routes: async (args) => {
98
+ const routes = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });
99
+ return { success: true, routes };
100
+ },
88
101
  submit_codegen_done: async (args) => ({
89
102
  success: true,
90
103
  summary: String(args.summary ?? "").trim(),
@@ -1 +1 @@
1
- {"version":3,"file":"toolLoopRunner.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport fs from \"node:fs/promises\";\nimport { persistToolCall } from \"../../services/toolcallPersist.service.js\";\nimport { EVENT_TYPES, EventType } from \"../../types/events.js\";\nimport { STYLE_TOKEN_KEYS } from \"../../types/styleConfig.js\";\nimport { createWorkspaceToolImpls } from \"../tools/implementations/factories.js\";\nimport { CoreFs } from \"../tools/implementations/workspaceDeps.js\";\nimport { parsePlannerTasksUnknown } from \"./plannerTaskParser.js\";\nimport {\n compactForModel,\n DEFAULT_CONTEXT_POLICY,\n normalizeReadFileArgs,\n redactFunctionCallArgs,\n ToolEvent,\n ToolLoopContextPolicy,\n} from \"./toolLoopContext.js\";\nimport {\n aiCallWithRetry,\n buildToolStatusMessage,\n recordToolEvent,\n serializeError,\n} from \"./toolLoopRunnerUtils.js\";\n\nexport type ToolLoopResult = {\n contents: any[];\n modelContents: any[];\n finalText: string;\n steps: number;\n terminalCall?: {\n name: string;\n args: Record<string, unknown>;\n response: unknown;\n };\n};\n\nexport type Logger = (message: string, eventType: EventType) => Promise<void>;\n\nexport type AiCallResponse = {\n functionCalls?: any[];\n text?: string;\n};\n\nexport type AiCallFn = (\n request: unknown,\n options: {\n tools?: Tool[];\n model?: string;\n toolCallingMode?: FunctionCallingConfigMode;\n },\n) => Promise<AiCallResponse>;\n\nexport type RunToolLoopOptions = {\n initialContents: any[];\n tools: Tool[];\n workspaceRoot: string;\n maxSteps?: number;\n toolCallingMode?: FunctionCallingConfigMode;\n terminalToolNames?: string[];\n keepFullTrace?: boolean;\n contextPolicy?: ToolLoopContextPolicy;\n aiCall: AiCallFn;\n logger: Logger;\n applyPatchAutoRetryMax?: number;\n aiCallAutoRetryMax?: number;\n aiCallAutoRetryBaseMs?: number;\n aiCallAutoRetryMaxMs?: number;\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>;\n};\n\nexport async function runToolLoop(\n options: RunToolLoopOptions,\n): Promise<ToolLoopResult> {\n const isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const styleTokenKeySet = new Set<string>(\n STYLE_TOKEN_KEYS as unknown as string[],\n );\n\n const {\n initialContents,\n tools,\n workspaceRoot,\n maxSteps = 30,\n toolCallingMode = FunctionCallingConfigMode.ANY,\n terminalToolNames = [],\n keepFullTrace = true,\n contextPolicy,\n aiCall,\n logger,\n applyPatchAutoRetryMax = 2,\n aiCallAutoRetryMax = 3, // must have it to try 3 times as gemini errors a lot due to high demand sometimes\n aiCallAutoRetryBaseMs = 400,\n aiCallAutoRetryMaxMs = 10_000,\n persistResponse,\n } = options;\n\n const nodeFs: CoreFs = {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n };\n\n const impls = createWorkspaceToolImpls({\n workspaceRoot,\n fs: nodeFs,\n });\n\n const toolHandlers: Record<string, (args: any) => Promise<any>> = {\n read_file: async (args) => {\n const path = String(args.path ?? \"\");\n const startLine =\n args.start_line === undefined ? undefined : Number(args.start_line);\n const endLine =\n args.end_line === undefined ? undefined : Number(args.end_line);\n const content = await impls.readFileImpl(path, startLine, endLine);\n return { path, content };\n },\n write_file: (args) =>\n impls.writeFileImpl(String(args.path ?? \"\"), String(args.content ?? \"\")),\n list_dir: async (args) => {\n const content = await impls.listDirImpl(\n String(args.path ?? \"\"),\n Number(args.depth ?? 1),\n );\n return { content };\n },\n search: async (args) => {\n const results = await impls.searchImpl(String(args.search_query ?? \"\"));\n return { results };\n },\n apply_patch: (args) =>\n impls.applyPatchImpl(String(args.patch_string ?? \"\")),\n update_global_styles: async (args) => {\n const result = await impls.updateGlobalStylesImpl(args);\n return result;\n },\n create_new_route: async (args) => {\n const parentRoute = String(args.parent_route ?? \"\");\n const routeName = String(args.route_name ?? \"\");\n const result = await impls.createNewRouteImpl(parentRoute, routeName);\n return result;\n },\n delete_element: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const result = await impls.deleteElementImpl(route, element_id);\n return result;\n },\n insert_element: async (args) => {\n const route = String(args.route ?? \"\");\n const parent_id = String(args.parent_id ?? \"\");\n const element: any = args.element;\n const result = await impls.insertElementImpl(route, parent_id, element);\n return result;\n },\n update_props: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const props: any = args.props;\n const result = await impls.updatePropsImpl({\n route,\n element_id,\n ...props,\n });\n return result;\n },\n update_classname: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const class_name = String(args.class_name ?? \"\");\n const result = await impls.updateClassNameImpl(\n route,\n element_id,\n class_name,\n );\n return result;\n },\n submit_codegen_done: async (args) => ({\n success: true,\n summary: String(args.summary ?? \"\").trim(),\n }),\n submit_planner_tasks: async (args) => {\n const tasks = parsePlannerTasksUnknown(args.planner_tasks);\n return { success: true, count: tasks.length };\n },\n };\n\n if (typeof aiCall !== \"function\") {\n throw new Error(\"Tool loop: aiCall is required.\");\n }\n\n const policy: Required<ToolLoopContextPolicy> = {\n ...DEFAULT_CONTEXT_POLICY,\n ...(contextPolicy ?? {}),\n };\n\n const toolEvents: ToolEvent[] = [];\n let applyPatchRetryCount = 0;\n\n const EXECUTION_GUIDE_MARKER = \"TOOL_LOOP_EXECUTION_GUIDE_V1\";\n const executionGuideInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `${EXECUTION_GUIDE_MARKER}\\n` +\n `Execution limit: At most ${maxSteps} assistant turn(s) in this tool loop. ` +\n `One turn = one assistant response in the tool loop.\\n` +\n `Complete the task in as few turns as possible and avoid unnecessary actions. Prioritize correctness.`,\n },\n ],\n };\n\n const fullTraceContents: any[] = keepFullTrace\n ? [...initialContents, executionGuideInstruction]\n : [];\n let modelContents: any[] = [...initialContents, executionGuideInstruction];\n const pinnedInitialCount = initialContents.length + 1;\n const pushBoth = (fullItem: any, modelItem: any) => {\n if (keepFullTrace) fullTraceContents.push(fullItem);\n modelContents.push(modelItem);\n };\n const pushModelOnly = (modelItem: any) => {\n modelContents.push(modelItem);\n };\n\n for (let step = 0; step < maxSteps; step++) {\n modelContents = compactForModel({\n initialCount: pinnedInitialCount,\n modelContents,\n toolEvents,\n policy,\n });\n\n if (policy.logApproxModelChars) {\n const approxChars = JSON.stringify(modelContents).length;\n console.log(\"Tool loop: approx model chars\", {\n approxChars,\n step: step + 1,\n });\n }\n\n let response: Awaited<ReturnType<AiCallFn>>;\n try {\n response = await aiCallWithRetry({\n aiCall,\n request: modelContents,\n options: { tools, toolCallingMode },\n retryMax: aiCallAutoRetryMax,\n retryBaseMs: aiCallAutoRetryBaseMs,\n retryMaxMs: aiCallAutoRetryMaxMs,\n step: step + 1,\n logger,\n });\n } catch (err) {\n logger(\n \"Tool loop: AI provider error; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n console.error(\"Tool loop: aiCall failed (provider/server side)\", err, {\n step: step + 1,\n error: serializeError(err),\n });\n\n const message =\n err instanceof Error ? err.message : JSON.stringify(err ?? null);\n const providerErrorInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `AI provider error (server-side). Do NOT clear or restart context; continue from the existing conversation state.\\n` +\n `Error: ${message}\\n` +\n `Next: retry the last request using the same context. If you were about to call tools, resend a valid tool call.`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(providerErrorInstruction);\n continue;\n }\n\n if (persistResponse) {\n try {\n await persistResponse(modelContents, response);\n } catch (err) {\n console.error(\"Tool loop: failed to persist response\", err, {\n step: step + 1,\n });\n }\n }\n\n const functionCalls = response.functionCalls ?? [];\n if (functionCalls.length === 0) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: (response.text ?? \"\").trim(),\n steps: step + 1,\n };\n }\n\n const signatureById = (() => {\n try {\n const candidates = Array.isArray((response as any)?.candidates)\n ? ((response as any).candidates as any[])\n : [];\n const parts = candidates?.[0]?.content?.parts;\n const arr = Array.isArray(parts) ? (parts as any[]) : [];\n const map = new Map<string, string>();\n for (const p of arr) {\n const fc = p?.functionCall;\n const id = fc?.id;\n const sig = p?.thoughtSignature ?? p?.thought_signature;\n if (typeof id === \"string\" && typeof sig === \"string\" && sig) {\n map.set(id, sig);\n }\n }\n return map;\n } catch {\n return new Map<string, string>();\n }\n })();\n\n for (let callIndex = 0; callIndex < functionCalls.length; callIndex++) {\n const call = functionCalls[callIndex];\n const name = call.name?.toString() ?? \"\";\n const args = (call.args ?? {}) as Record<string, unknown>;\n const thoughtSignature: string | undefined = (() => {\n const direct =\n (call as any)?.thought_signature ?? (call as any)?.thoughtSignature;\n if (typeof direct === \"string\" && direct) return direct;\n const id = (call as any)?.id;\n if (typeof id === \"string\" && signatureById.has(id)) {\n return signatureById.get(id);\n }\n return undefined;\n })();\n\n if (!name) {\n logger(\n \"Tool loop: malformed function call from model; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n const malformedInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `Malformed function call received (missing tool name). Do NOT clear or restart context.\\n` +\n `Resend a single valid tool call with a non-empty name and JSON args.\\n` +\n `Bad call: ${JSON.stringify(call ?? null).slice(0, 1500)}`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(malformedInstruction);\n modelContents.push(malformedInstruction);\n continue;\n }\n\n const handler = toolHandlers[name];\n const handlerMissingResult = !handler\n ? {\n success: false,\n error: `No handler registered for \"${name}\".`,\n error_detail: {\n name: \"MissingToolHandlerError\",\n message: `No handler registered for \"${name}\".`,\n },\n }\n : null;\n\n let effectiveArgs: Record<string, unknown> = args;\n let readFileMeta: {\n start: number;\n end: number;\n wasCapped: boolean;\n } | null = null;\n if (name === \"read_file\") {\n const normalized = normalizeReadFileArgs(\n effectiveArgs,\n policy.readFileDefaultMaxLines,\n );\n effectiveArgs = normalized.effectiveArgs;\n readFileMeta = {\n start: normalized.start,\n end: normalized.end,\n wasCapped: normalized.wasCapped,\n };\n }\n\n if (name === \"update_global_styles\") {\n // Be forgiving: models sometimes include a legacy \"tokens\" key or other junk.\n // We accept the call as long as at least one valid token key/value is provided.\n const tokensMaybe = (effectiveArgs as any)?.tokens;\n const normalized: Record<string, unknown> = {};\n\n if (isPlainObject(tokensMaybe)) {\n for (const [k, v] of Object.entries(tokensMaybe)) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n }\n\n for (const [k, v] of Object.entries(effectiveArgs ?? {})) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n\n effectiveArgs = normalized;\n }\n\n logger(\n buildToolStatusMessage(name, effectiveArgs, readFileMeta),\n EVENT_TYPES.STEP_STARTED,\n );\n\n const modelArgs = redactFunctionCallArgs(name, effectiveArgs);\n\n const functionCallPart = {\n functionCall: {\n name,\n args: effectiveArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const functionCallPartModel = {\n functionCall: {\n name,\n args: modelArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const assistantFull = {\n role: \"model\",\n parts: [\n {\n ...functionCallPart,\n },\n ],\n };\n\n const assistantModel = {\n role: \"model\",\n parts: [\n {\n ...functionCallPartModel,\n },\n ],\n };\n\n if (keepFullTrace) {\n pushBoth(assistantFull, assistantModel);\n } else {\n pushModelOnly(assistantModel);\n }\n\n let toolResultRaw: unknown;\n if (handlerMissingResult) {\n toolResultRaw = handlerMissingResult;\n } else {\n try {\n if (name === \"update_global_styles\") {\n const flatKeys = Object.keys(effectiveArgs ?? {}).filter((k) =>\n styleTokenKeySet.has(k),\n );\n if (flatKeys.length === 0) {\n toolResultRaw = {\n success: false,\n error: \"must include at least one token key/value\",\n error_detail: {\n name: \"InvalidToolArgumentsError\",\n message:\n 'update_global_styles requires at least one token key/value (e.g. { radius: \"0.75rem\" }).',\n },\n note: \"Resend update_global_styles with at least one token key/value, or skip this tool call.\",\n };\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } catch (err) {\n logger(`AI tool: ${name} failed`, EVENT_TYPES.STEP_ERROR);\n console.error(\"Tool loop: handler threw\", err, {\n tool: name,\n step: step + 1,\n });\n toolResultRaw = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n error_detail: serializeError(err),\n note: \"Tool handler threw. Inspect error_detail and retry with corrected args or a different approach.\",\n };\n }\n }\n let toolResult: unknown = toolResultRaw;\n\n if (name === \"read_file\" && readFileMeta) {\n const path = String(effectiveArgs.path ?? \"\");\n\n const jsonPayload =\n (toolResultRaw as any)?.kind === \"json\"\n ? (toolResultRaw as any)?.json\n : undefined;\n if (jsonPayload !== undefined) {\n // Token-efficient: return JSON as structured data (no double-stringifying).\n toolResult = { path, json: jsonPayload };\n } else {\n const rawContent =\n typeof (toolResultRaw as any)?.content === \"string\"\n ? String((toolResultRaw as any).content)\n : typeof toolResultRaw === \"string\"\n ? toolResultRaw\n : JSON.stringify(toolResultRaw ?? null);\n\n toolResult = {\n path,\n start_line: readFileMeta.start,\n end_line: readFileMeta.end,\n truncated: readFileMeta.wasCapped,\n content: rawContent,\n note: readFileMeta.wasCapped\n ? `Capped to ${policy.readFileDefaultMaxLines} lines. Request more with start_line/end_line.`\n : undefined,\n };\n }\n }\n\n try {\n await persistToolCall(name, modelArgs, toolResult);\n } catch (err) {\n console.error(\"Tool loop: failed to persist tool call\", err, {\n tool: name,\n step: step + 1,\n });\n }\n\n const responseFull = {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name,\n response: toolResult,\n },\n },\n ],\n };\n\n if (keepFullTrace) {\n fullTraceContents.push(responseFull);\n }\n modelContents.push(responseFull);\n\n if (\n name === \"apply_patch\" &&\n (toolResult as any)?.success === false &&\n applyPatchAutoRetryMax > 0 &&\n applyPatchRetryCount < applyPatchAutoRetryMax\n ) {\n applyPatchRetryCount += 1;\n\n const error = String((toolResult as any)?.error ?? \"unknown error\");\n const debugFiles = Array.isArray((toolResult as any)?.debug?.files)\n ? ((toolResult as any).debug.files as Array<{\n path?: string;\n head?: string;\n }>)\n : [];\n\n const debugText =\n debugFiles.length > 0\n ? `\\n\\nFILE SNAPSHOTS (for regenerating the patch):\\n${debugFiles\n .slice(0, 3)\n .map(\n (f) =>\n `--- ${String(f.path ?? \"\")} ---\\n${String(\n f.head ?? \"\",\n )}\\n--- end ---`,\n )\n .join(\"\\n\\n\")}`\n : \"\";\n\n const retryInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `apply_patch failed (attempt ${applyPatchRetryCount}/${applyPatchAutoRetryMax}): ${error}\\n` +\n `Regenerate a patch that matches the current file contents. ` +\n `For large rewrites, prefer write_file(path, content) or Delete+Add instead of Update.` +\n debugText,\n },\n ],\n };\n\n if (keepFullTrace) fullTraceContents.push(retryInstruction);\n modelContents.push(retryInstruction);\n }\n\n recordToolEvent({\n toolEvents,\n name,\n effectiveArgs,\n modelArgs,\n readFileMeta,\n toolResult,\n toolResultRaw,\n });\n\n if (terminalToolNames.includes(name)) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: \"\",\n steps: step + 1,\n terminalCall: { name, args: effectiveArgs, response: toolResultRaw },\n };\n }\n }\n }\n\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: `Stopped: max steps reached (${maxSteps}).`,\n steps: maxSteps,\n };\n}\n"]}
1
+ {"version":3,"file":"toolLoopRunner.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport fs from \"node:fs/promises\";\nimport { persistToolCall } from \"../../services/toolcallPersist.service.js\";\nimport { EVENT_TYPES, EventType } from \"../../types/events.js\";\nimport { STYLE_TOKEN_KEYS } from \"../../types/styleConfig.js\";\nimport { createWorkspaceToolImpls } from \"../tools/implementations/factories.js\";\nimport { CoreFs } from \"../tools/implementations/workspaceDeps.js\";\nimport { parsePlannerTasksUnknown } from \"./plannerTaskParser.js\";\nimport { getAvailableRoutes } from \"../tools/helpers/pageConfigJson.helpers.js\";\nimport {\n compactForModel,\n DEFAULT_CONTEXT_POLICY,\n normalizeReadFileArgs,\n redactFunctionCallArgs,\n ToolEvent,\n ToolLoopContextPolicy,\n} from \"./toolLoopContext.js\";\nimport {\n aiCallWithRetry,\n buildToolStatusMessage,\n recordToolEvent,\n serializeError,\n} from \"./toolLoopRunnerUtils.js\";\n\nexport type ToolLoopResult = {\n contents: any[];\n modelContents: any[];\n finalText: string;\n steps: number;\n terminalCall?: {\n name: string;\n args: Record<string, unknown>;\n response: unknown;\n };\n};\n\nexport type Logger = (message: string, eventType: EventType) => Promise<void>;\n\nexport type AiCallResponse = {\n functionCalls?: any[];\n text?: string;\n};\n\nexport type AiCallFn = (\n request: unknown,\n options: {\n tools?: Tool[];\n model?: string;\n toolCallingMode?: FunctionCallingConfigMode;\n },\n) => Promise<AiCallResponse>;\n\nexport type RunToolLoopOptions = {\n initialContents: any[];\n tools: Tool[];\n workspaceRoot: string;\n maxSteps?: number;\n toolCallingMode?: FunctionCallingConfigMode;\n terminalToolNames?: string[];\n keepFullTrace?: boolean;\n contextPolicy?: ToolLoopContextPolicy;\n aiCall: AiCallFn;\n logger: Logger;\n applyPatchAutoRetryMax?: number;\n aiCallAutoRetryMax?: number;\n aiCallAutoRetryBaseMs?: number;\n aiCallAutoRetryMaxMs?: number;\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>;\n};\n\nexport async function runToolLoop(\n options: RunToolLoopOptions,\n): Promise<ToolLoopResult> {\n const isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const styleTokenKeySet = new Set<string>(\n STYLE_TOKEN_KEYS as unknown as string[],\n );\n\n const {\n initialContents,\n tools,\n workspaceRoot,\n maxSteps = 30,\n toolCallingMode = FunctionCallingConfigMode.ANY,\n terminalToolNames = [],\n keepFullTrace = true,\n contextPolicy,\n aiCall,\n logger,\n applyPatchAutoRetryMax = 2,\n aiCallAutoRetryMax = 3, // must have it to try 3 times as gemini errors a lot due to high demand sometimes\n aiCallAutoRetryBaseMs = 400,\n aiCallAutoRetryMaxMs = 10_000,\n persistResponse,\n } = options;\n\n const nodeFs: CoreFs = {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n };\n\n const impls = createWorkspaceToolImpls({\n workspaceRoot,\n fs: nodeFs,\n });\n\n const toolHandlers: Record<string, (args: any) => Promise<any>> = {\n read_file: async (args) => {\n const path = String(args.path ?? \"\");\n const startLine =\n args.start_line === undefined ? undefined : Number(args.start_line);\n const endLine =\n args.end_line === undefined ? undefined : Number(args.end_line);\n const content = await impls.readFileImpl(path, startLine, endLine);\n return { path, content };\n },\n write_file: (args) =>\n impls.writeFileImpl(String(args.path ?? \"\"), String(args.content ?? \"\")),\n list_dir: async (args) => {\n const content = await impls.listDirImpl(\n String(args.path ?? \"\"),\n Number(args.depth ?? 1),\n );\n return { content };\n },\n search: async (args) => {\n const results = await impls.searchImpl(String(args.search_query ?? \"\"));\n return { results };\n },\n apply_patch: (args) =>\n impls.applyPatchImpl(String(args.patch_string ?? \"\")),\n update_global_styles: async (args) => {\n const result = await impls.updateGlobalStylesImpl(args);\n return result;\n },\n create_new_route: async (args) => {\n const parentRoute = String(args.parent_route ?? \"\");\n const routeName = String(args.route_name ?? \"\");\n const result = await impls.createNewRouteImpl(parentRoute, routeName);\n return result;\n },\n delete_element: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const result = await impls.deleteElementImpl(route, element_id);\n return result;\n },\n insert_element: async (args) => {\n const route = String(args.route ?? \"\");\n const parent_id = String(args.parent_id ?? \"\");\n const element: any = args.element;\n const result = await impls.insertElementImpl(route, parent_id, element);\n if (!result.success) {\n const available = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });\n return {\n success: false,\n error: `insert_element failed: ${result.error}. Available routes are: ${JSON.stringify(available)}. If you intend to create a new route, create it using the 'create_new_route' tool.`,\n available_routes: available,\n };\n }\n return result;\n },\n update_props: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const props: any = args.props;\n const result = await impls.updatePropsImpl({\n route,\n element_id,\n ...props,\n });\n return result;\n },\n update_classname: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const class_name = String(args.class_name ?? \"\");\n const result = await impls.updateClassNameImpl(\n route,\n element_id,\n class_name,\n );\n return result;\n },\n get_available_routes: async (args) => {\n const routes = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });\n return { success: true, routes };\n },\n submit_codegen_done: async (args) => ({\n success: true,\n summary: String(args.summary ?? \"\").trim(),\n }),\n submit_planner_tasks: async (args) => {\n const tasks = parsePlannerTasksUnknown(args.planner_tasks);\n return { success: true, count: tasks.length };\n },\n };\n\n if (typeof aiCall !== \"function\") {\n throw new Error(\"Tool loop: aiCall is required.\");\n }\n\n const policy: Required<ToolLoopContextPolicy> = {\n ...DEFAULT_CONTEXT_POLICY,\n ...(contextPolicy ?? {}),\n };\n\n const toolEvents: ToolEvent[] = [];\n let applyPatchRetryCount = 0;\n\n const EXECUTION_GUIDE_MARKER = \"TOOL_LOOP_EXECUTION_GUIDE_V1\";\n const executionGuideInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `${EXECUTION_GUIDE_MARKER}\\n` +\n `Execution limit: At most ${maxSteps} assistant turn(s) in this tool loop. ` +\n `One turn = one assistant response in the tool loop.\\n` +\n `Complete the task in as few turns as possible and avoid unnecessary actions. Prioritize correctness.`,\n },\n ],\n };\n\n const fullTraceContents: any[] = keepFullTrace\n ? [...initialContents, executionGuideInstruction]\n : [];\n let modelContents: any[] = [...initialContents, executionGuideInstruction];\n const pinnedInitialCount = initialContents.length + 1;\n const pushBoth = (fullItem: any, modelItem: any) => {\n if (keepFullTrace) fullTraceContents.push(fullItem);\n modelContents.push(modelItem);\n };\n const pushModelOnly = (modelItem: any) => {\n modelContents.push(modelItem);\n };\n\n for (let step = 0; step < maxSteps; step++) {\n modelContents = compactForModel({\n initialCount: pinnedInitialCount,\n modelContents,\n toolEvents,\n policy,\n });\n\n if (policy.logApproxModelChars) {\n const approxChars = JSON.stringify(modelContents).length;\n console.log(\"Tool loop: approx model chars\", {\n approxChars,\n step: step + 1,\n });\n }\n\n let response: Awaited<ReturnType<AiCallFn>>;\n try {\n response = await aiCallWithRetry({\n aiCall,\n request: modelContents,\n options: { tools, toolCallingMode },\n retryMax: aiCallAutoRetryMax,\n retryBaseMs: aiCallAutoRetryBaseMs,\n retryMaxMs: aiCallAutoRetryMaxMs,\n step: step + 1,\n logger,\n });\n } catch (err) {\n logger(\n \"Tool loop: AI provider error; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n console.error(\"Tool loop: aiCall failed (provider/server side)\", err, {\n step: step + 1,\n error: serializeError(err),\n });\n\n const message =\n err instanceof Error ? err.message : JSON.stringify(err ?? null);\n const providerErrorInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `AI provider error (server-side). Do NOT clear or restart context; continue from the existing conversation state.\\n` +\n `Error: ${message}\\n` +\n `Next: retry the last request using the same context. If you were about to call tools, resend a valid tool call.`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(providerErrorInstruction);\n continue;\n }\n\n if (persistResponse) {\n try {\n await persistResponse(modelContents, response);\n } catch (err) {\n console.error(\"Tool loop: failed to persist response\", err, {\n step: step + 1,\n });\n }\n }\n\n const functionCalls = response.functionCalls ?? [];\n if (functionCalls.length === 0) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: (response.text ?? \"\").trim(),\n steps: step + 1,\n };\n }\n\n const signatureById = (() => {\n try {\n const candidates = Array.isArray((response as any)?.candidates)\n ? ((response as any).candidates as any[])\n : [];\n const parts = candidates?.[0]?.content?.parts;\n const arr = Array.isArray(parts) ? (parts as any[]) : [];\n const map = new Map<string, string>();\n for (const p of arr) {\n const fc = p?.functionCall;\n const id = fc?.id;\n const sig = p?.thoughtSignature ?? p?.thought_signature;\n if (typeof id === \"string\" && typeof sig === \"string\" && sig) {\n map.set(id, sig);\n }\n }\n return map;\n } catch {\n return new Map<string, string>();\n }\n })();\n\n for (let callIndex = 0; callIndex < functionCalls.length; callIndex++) {\n const call = functionCalls[callIndex];\n const name = call.name?.toString() ?? \"\";\n const args = (call.args ?? {}) as Record<string, unknown>;\n const thoughtSignature: string | undefined = (() => {\n const direct =\n (call as any)?.thought_signature ?? (call as any)?.thoughtSignature;\n if (typeof direct === \"string\" && direct) return direct;\n const id = (call as any)?.id;\n if (typeof id === \"string\" && signatureById.has(id)) {\n return signatureById.get(id);\n }\n return undefined;\n })();\n\n if (!name) {\n logger(\n \"Tool loop: malformed function call from model; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n const malformedInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `Malformed function call received (missing tool name). Do NOT clear or restart context.\\n` +\n `Resend a single valid tool call with a non-empty name and JSON args.\\n` +\n `Bad call: ${JSON.stringify(call ?? null).slice(0, 1500)}`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(malformedInstruction);\n modelContents.push(malformedInstruction);\n continue;\n }\n\n const handler = toolHandlers[name];\n const handlerMissingResult = !handler\n ? {\n success: false,\n error: `No handler registered for \"${name}\".`,\n error_detail: {\n name: \"MissingToolHandlerError\",\n message: `No handler registered for \"${name}\".`,\n },\n }\n : null;\n\n let effectiveArgs: Record<string, unknown> = args;\n let readFileMeta: {\n start: number;\n end: number;\n wasCapped: boolean;\n } | null = null;\n if (name === \"read_file\") {\n const normalized = normalizeReadFileArgs(\n effectiveArgs,\n policy.readFileDefaultMaxLines,\n );\n effectiveArgs = normalized.effectiveArgs;\n readFileMeta = {\n start: normalized.start,\n end: normalized.end,\n wasCapped: normalized.wasCapped,\n };\n }\n\n if (name === \"update_global_styles\") {\n // Be forgiving: models sometimes include a legacy \"tokens\" key or other junk.\n // We accept the call as long as at least one valid token key/value is provided.\n const tokensMaybe = (effectiveArgs as any)?.tokens;\n const normalized: Record<string, unknown> = {};\n\n if (isPlainObject(tokensMaybe)) {\n for (const [k, v] of Object.entries(tokensMaybe)) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n }\n\n for (const [k, v] of Object.entries(effectiveArgs ?? {})) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n\n effectiveArgs = normalized;\n }\n\n logger(\n buildToolStatusMessage(name, effectiveArgs, readFileMeta),\n EVENT_TYPES.STEP_STARTED,\n );\n\n const modelArgs = redactFunctionCallArgs(name, effectiveArgs);\n\n const functionCallPart = {\n functionCall: {\n name,\n args: effectiveArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const functionCallPartModel = {\n functionCall: {\n name,\n args: modelArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const assistantFull = {\n role: \"model\",\n parts: [\n {\n ...functionCallPart,\n },\n ],\n };\n\n const assistantModel = {\n role: \"model\",\n parts: [\n {\n ...functionCallPartModel,\n },\n ],\n };\n\n if (keepFullTrace) {\n pushBoth(assistantFull, assistantModel);\n } else {\n pushModelOnly(assistantModel);\n }\n\n let toolResultRaw: unknown;\n if (handlerMissingResult) {\n toolResultRaw = handlerMissingResult;\n } else {\n try {\n if (name === \"update_global_styles\") {\n const flatKeys = Object.keys(effectiveArgs ?? {}).filter((k) =>\n styleTokenKeySet.has(k),\n );\n if (flatKeys.length === 0) {\n toolResultRaw = {\n success: false,\n error: \"must include at least one token key/value\",\n error_detail: {\n name: \"InvalidToolArgumentsError\",\n message:\n 'update_global_styles requires at least one token key/value (e.g. { radius: \"0.75rem\" }).',\n },\n note: \"Resend update_global_styles with at least one token key/value, or skip this tool call.\",\n };\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } catch (err) {\n logger(`AI tool: ${name} failed`, EVENT_TYPES.STEP_ERROR);\n console.error(\"Tool loop: handler threw\", err, {\n tool: name,\n step: step + 1,\n });\n toolResultRaw = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n error_detail: serializeError(err),\n note: \"Tool handler threw. Inspect error_detail and retry with corrected args or a different approach.\",\n };\n }\n }\n let toolResult: unknown = toolResultRaw;\n\n if (name === \"read_file\" && readFileMeta) {\n const path = String(effectiveArgs.path ?? \"\");\n\n const jsonPayload =\n (toolResultRaw as any)?.kind === \"json\"\n ? (toolResultRaw as any)?.json\n : undefined;\n if (jsonPayload !== undefined) {\n // Token-efficient: return JSON as structured data (no double-stringifying).\n toolResult = { path, json: jsonPayload };\n } else {\n const rawContent =\n typeof (toolResultRaw as any)?.content === \"string\"\n ? String((toolResultRaw as any).content)\n : typeof toolResultRaw === \"string\"\n ? toolResultRaw\n : JSON.stringify(toolResultRaw ?? null);\n\n toolResult = {\n path,\n start_line: readFileMeta.start,\n end_line: readFileMeta.end,\n truncated: readFileMeta.wasCapped,\n content: rawContent,\n note: readFileMeta.wasCapped\n ? `Capped to ${policy.readFileDefaultMaxLines} lines. Request more with start_line/end_line.`\n : undefined,\n };\n }\n }\n\n try {\n await persistToolCall(name, modelArgs, toolResult);\n } catch (err) {\n console.error(\"Tool loop: failed to persist tool call\", err, {\n tool: name,\n step: step + 1,\n });\n }\n\n const responseFull = {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name,\n response: toolResult,\n },\n },\n ],\n };\n\n if (keepFullTrace) {\n fullTraceContents.push(responseFull);\n }\n modelContents.push(responseFull);\n\n if (\n name === \"apply_patch\" &&\n (toolResult as any)?.success === false &&\n applyPatchAutoRetryMax > 0 &&\n applyPatchRetryCount < applyPatchAutoRetryMax\n ) {\n applyPatchRetryCount += 1;\n\n const error = String((toolResult as any)?.error ?? \"unknown error\");\n const debugFiles = Array.isArray((toolResult as any)?.debug?.files)\n ? ((toolResult as any).debug.files as Array<{\n path?: string;\n head?: string;\n }>)\n : [];\n\n const debugText =\n debugFiles.length > 0\n ? `\\n\\nFILE SNAPSHOTS (for regenerating the patch):\\n${debugFiles\n .slice(0, 3)\n .map(\n (f) =>\n `--- ${String(f.path ?? \"\")} ---\\n${String(\n f.head ?? \"\",\n )}\\n--- end ---`,\n )\n .join(\"\\n\\n\")}`\n : \"\";\n\n const retryInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `apply_patch failed (attempt ${applyPatchRetryCount}/${applyPatchAutoRetryMax}): ${error}\\n` +\n `Regenerate a patch that matches the current file contents. ` +\n `For large rewrites, prefer write_file(path, content) or Delete+Add instead of Update.` +\n debugText,\n },\n ],\n };\n\n if (keepFullTrace) fullTraceContents.push(retryInstruction);\n modelContents.push(retryInstruction);\n }\n\n recordToolEvent({\n toolEvents,\n name,\n effectiveArgs,\n modelArgs,\n readFileMeta,\n toolResult,\n toolResultRaw,\n });\n\n if (terminalToolNames.includes(name)) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: \"\",\n steps: step + 1,\n terminalCall: { name, args: effectiveArgs, response: toolResultRaw },\n };\n }\n }\n }\n\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: `Stopped: max steps reached (${maxSteps}).`,\n steps: maxSteps,\n };\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { BuilderElement } from "../../../types/elements.js";
2
+ import type { CoreFs } from "../implementations/workspaceDeps.js";
2
3
  export type PageConfigJson = {
3
4
  elements: BuilderElement[];
4
5
  };
@@ -12,4 +13,16 @@ export declare const ensureElementIds: (elements: BuilderElement[], existingIds:
12
13
  export declare const findElementById: (elements: BuilderElement[], elementId: string) => BuilderElement | null;
13
14
  export declare const deleteElementById: (elements: BuilderElement[], id: string) => boolean;
14
15
  export declare const writeFileAtomic: (filePath: string, content: string) => Promise<void>;
16
+ export declare const getAvailableRoutes: (deps: {
17
+ workspaceRoot: string;
18
+ fs: {
19
+ safeReadDir: (absoluteDir: string) => Promise<Array<{
20
+ name: string;
21
+ isDirectory: () => boolean;
22
+ isFile: () => boolean;
23
+ }>>;
24
+ };
25
+ }) => Promise<string[]>;
26
+ export declare const matchRoute: (physicalRoute: string, requestedRoute: string) => boolean;
27
+ export declare const resolvePageConfigJsonPath: (workspaceRoot: string, route: string, fs: CoreFs) => Promise<string>;
15
28
  //# sourceMappingURL=pageConfigJson.helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pageConfigJson.helpers.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/helpers/pageConfigJson.helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MAAM,EAQ5D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,YAM5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,eAAe,MAAM,EAAE,OAAO,MAAM,WAOzE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,KAAG,cAkBrD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,cAAc,WACO,CAAC;AAEtE,eAAO,MAAM,iBAAiB,GAAI,UAAU,cAAc,EAAE,gBAa3D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,UAAU,cAAc,EAAE,EAC1B,aAAa,GAAG,CAAC,MAAM,CAAC,SA0BzB,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,cAAc,EAAE,EAC1B,WAAW,MAAM,KAChB,cAAc,GAAG,IAkBnB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,cAAc,EAAE,EAC1B,IAAI,MAAM,KACT,OAkBF,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,UAAU,MAAM,EAAE,SAAS,MAAM,kBAkDtE,CAAC"}
1
+ {"version":3,"file":"pageConfigJson.helpers.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/helpers/pageConfigJson.helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MAAM,EAQ5D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,YAM5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,eAAe,MAAM,EAAE,OAAO,MAAM,WAOzE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,KAAG,cAkBrD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,cAAc,WACO,CAAC;AAEtE,eAAO,MAAM,iBAAiB,GAAI,UAAU,cAAc,EAAE,gBAa3D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,UAAU,cAAc,EAAE,EAC1B,aAAa,GAAG,CAAC,MAAM,CAAC,SA0BzB,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,cAAc,EAAE,EAC1B,WAAW,MAAM,KAChB,cAAc,GAAG,IAkBnB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,cAAc,EAAE,EAC1B,IAAI,MAAM,KACT,OAkBF,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,UAAU,MAAM,EAAE,SAAS,MAAM,kBAkDtE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,MAAM;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE;QACF,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;YAClD,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,OAAO,CAAC;YAC3B,MAAM,EAAE,MAAM,OAAO,CAAC;SACvB,CAAC,CAAC,CAAC;KACL,CAAC;CACH,KAAG,OAAO,CAAC,MAAM,EAAE,CAoCnB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,eAAe,MAAM,EAAE,gBAAgB,MAAM,KAAG,OA+C1E,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,OAAO,MAAM,EACb,IAAI,MAAM,KACT,OAAO,CAAC,MAAM,CAsBhB,CAAC"}
@@ -181,4 +181,98 @@ export const writeFileAtomic = async (filePath, content) => {
181
181
  throw err;
182
182
  }
183
183
  };
184
+ export const getAvailableRoutes = async (deps) => {
185
+ const { workspaceRoot, fs } = deps;
186
+ const appDir = toWorkspacePath(workspaceRoot, "app");
187
+ const routes = [];
188
+ const scan = async (dirPath) => {
189
+ let entries;
190
+ try {
191
+ entries = await fs.safeReadDir(dirPath);
192
+ }
193
+ catch {
194
+ return;
195
+ }
196
+ let hasPageConfig = false;
197
+ for (const entry of entries) {
198
+ if (entry.isFile() && entry.name === "pageConfig.json") {
199
+ hasPageConfig = true;
200
+ break;
201
+ }
202
+ }
203
+ if (hasPageConfig) {
204
+ const rel = path.relative(appDir, dirPath);
205
+ const routeStr = "/" + rel.replace(/\\/g, "/");
206
+ routes.push(routeStr === "/" ? "/" : routeStr.replace(/\/$/, ""));
207
+ }
208
+ for (const entry of entries) {
209
+ if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
210
+ await scan(path.join(dirPath, entry.name));
211
+ }
212
+ }
213
+ };
214
+ await scan(appDir);
215
+ return routes.sort();
216
+ };
217
+ export const matchRoute = (physicalRoute, requestedRoute) => {
218
+ const physSegs = normalizeRouteSegments(physicalRoute);
219
+ const reqSegs = normalizeRouteSegments(requestedRoute);
220
+ let pIdx = 0;
221
+ let rIdx = 0;
222
+ while (pIdx < physSegs.length && rIdx < reqSegs.length) {
223
+ const phys = physSegs[pIdx];
224
+ const req = reqSegs[rIdx];
225
+ // Catch-all (e.g. [...slug] or [[...slug]])
226
+ if (phys.startsWith("[") && phys.endsWith("]") && phys.includes("...")) {
227
+ return true;
228
+ }
229
+ // Regular dynamic segment (e.g. [id])
230
+ if (phys.startsWith("[") && phys.endsWith("]")) {
231
+ pIdx++;
232
+ rIdx++;
233
+ continue;
234
+ }
235
+ // Exact match
236
+ if (phys.toLowerCase() === req.toLowerCase()) {
237
+ pIdx++;
238
+ rIdx++;
239
+ continue;
240
+ }
241
+ return false;
242
+ }
243
+ // Handle case where we ran out of requested segments but have remaining physical segments
244
+ // e.g. physical is /blog/[[...slug]] (optional catch-all) and request is /blog
245
+ if (rIdx === reqSegs.length && pIdx < physSegs.length) {
246
+ // All remaining physical segments must be optional catch-alls (e.g., [[...slug]])
247
+ for (let i = pIdx; i < physSegs.length; i++) {
248
+ const phys = physSegs[i];
249
+ if (!(phys.startsWith("[[") && phys.endsWith("]]") && phys.includes("..."))) {
250
+ return false;
251
+ }
252
+ }
253
+ return true;
254
+ }
255
+ return pIdx === physSegs.length && rIdx === reqSegs.length;
256
+ };
257
+ export const resolvePageConfigJsonPath = async (workspaceRoot, route, fs) => {
258
+ // 1. Try exact match first
259
+ const exactPath = getPageConfigJsonPath(workspaceRoot, route);
260
+ try {
261
+ await fs.stat(exactPath);
262
+ return exactPath;
263
+ }
264
+ catch {
265
+ // Exact file does not exist, let's resolve dynamically
266
+ }
267
+ // 2. Fetch all available routes in the workspace
268
+ const available = await getAvailableRoutes({ workspaceRoot, fs });
269
+ // 3. Find first matching route
270
+ for (const physRoute of available) {
271
+ if (matchRoute(physRoute, route)) {
272
+ return getPageConfigJsonPath(workspaceRoot, physRoute);
273
+ }
274
+ }
275
+ // 4. Fallback: if no match, just return the exact path
276
+ return exactPath;
277
+ };
184
278
  //# sourceMappingURL=pageConfigJson.helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pageConfigJson.helpers.js","sourceRoot":"","sources":["../../../../src/ai/tools/helpers/pageConfigJson.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport { createElementId } from \"./elementid.helpers.js\";\nimport { toWorkspacePath } from \"./fileSystem.helpers.js\";\n\nexport type PageConfigJson = {\n elements: BuilderElement[];\n};\n\nexport const normalizeRouteSegments = (route: string): string[] => {\n const raw = String(route ?? \"\").trim();\n if (!raw || raw === \"/\") return [];\n return raw\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .map((s) => s.trim())\n .filter(Boolean);\n};\n\nexport const isSafeSegment = (segment: string) => {\n const s = String(segment ?? \"\").trim();\n if (!s) return false;\n if (s === \".\" || s === \"..\") return false;\n if (s.includes(\"/\") || s.includes(\"\\\\\")) return false;\n return true;\n};\n\nexport const getPageConfigJsonPath = (workspaceRoot: string, route: string) => {\n const segments = normalizeRouteSegments(route);\n if (segments.some((s) => !isSafeSegment(s))) {\n throw new Error(\"invalid route\");\n }\n const rel = path.posix.join(\"app\", ...segments, \"pageConfig.json\");\n return toWorkspacePath(workspaceRoot, rel);\n};\n\nexport const parsePageConfigJson = (content: string): PageConfigJson => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(String(content ?? \"\"));\n } catch {\n throw new Error(\"pageConfig.json is not valid JSON\");\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"pageConfig.json must be an object\");\n }\n\n const elements = (parsed as any).elements;\n if (!Array.isArray(elements)) {\n throw new Error('pageConfig.json must contain \"elements\" array');\n }\n\n return { elements: elements as BuilderElement[] };\n};\n\nexport const stringifyPageConfigJson = (config: PageConfigJson) =>\n JSON.stringify({ elements: config.elements ?? [] }, null, 2) + \"\\n\";\n\nexport const extractAllIdsDeep = (elements: BuilderElement[]) => {\n const ids = new Set<string>();\n const walk = (arr: BuilderElement[]) => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n const id = (el as any).id;\n if (typeof id === \"string\" && id.trim()) ids.add(id.trim());\n const children = (el as any).children;\n if (Array.isArray(children)) walk(children as BuilderElement[]);\n }\n };\n walk(Array.isArray(elements) ? elements : []);\n return ids;\n};\n\nexport const ensureElementIds = (\n elements: BuilderElement[],\n existingIds: Set<string>,\n) => {\n const seen = new Set<string>();\n const walk = (arr: BuilderElement[]) => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n\n const anyEl = el as any;\n const currentId = typeof anyEl.id === \"string\" ? anyEl.id.trim() : \"\";\n if (!currentId || seen.has(currentId)) {\n const newId = createElementId(existingIds);\n anyEl.id = newId;\n existingIds.add(newId);\n seen.add(newId);\n } else {\n anyEl.id = currentId;\n existingIds.add(currentId);\n seen.add(currentId);\n }\n\n if (Array.isArray(anyEl.children)) {\n walk(anyEl.children as BuilderElement[]);\n }\n }\n };\n walk(elements);\n};\n\nexport const findElementById = (\n elements: BuilderElement[],\n elementId: string,\n): BuilderElement | null => {\n const id = String(elementId ?? \"\").trim();\n if (!id) return null;\n\n const walk = (arr: BuilderElement[]): BuilderElement | null => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n if ((el as any).id === id) return el;\n const children = (el as any).children;\n if (Array.isArray(children)) {\n const found = walk(children as BuilderElement[]);\n if (found) return found;\n }\n }\n return null;\n };\n\n return walk(elements);\n};\n\nexport const deleteElementById = (\n elements: BuilderElement[],\n id: string,\n): boolean => {\n const target = String(id ?? \"\").trim();\n if (!target) return false;\n\n let deleted = false;\n const walk = (arr: BuilderElement[]) => {\n for (let idx = arr.length - 1; idx >= 0; idx--) {\n const el = arr[idx] as any;\n if (el?.id === target) {\n arr.splice(idx, 1);\n deleted = true;\n continue;\n }\n if (Array.isArray(el?.children)) walk(el.children as BuilderElement[]);\n }\n };\n walk(elements);\n return deleted;\n};\n\nexport const writeFileAtomic = async (filePath: string, content: string) => {\n const dir = path.dirname(filePath);\n const base = path.basename(filePath);\n const tmp = path.join(\n dir,\n `.qwintly_tmp_${base}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n const bak = path.join(\n dir,\n `.qwintly_bak_${base}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n try {\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(tmp, content ?? \"\", \"utf-8\");\n\n // Windows rename doesn't overwrite; do a 2-step swap.\n try {\n await fs.rename(filePath, bak);\n await fs.rename(tmp, filePath);\n await fs.rm(bak, { force: true });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n // No previous file; just put the temp file in place.\n await fs.rename(tmp, filePath);\n } else {\n throw err;\n }\n }\n } catch (err) {\n // rollback best-effort\n try {\n await fs.rm(tmp, { force: true });\n } catch {\n // ignore\n }\n try {\n await fs.stat(bak);\n try {\n await fs.rm(filePath, { force: true });\n } catch {\n // ignore\n }\n await fs.rename(bak, filePath);\n } catch {\n // ignore\n }\n throw err;\n }\n};\n"]}
1
+ {"version":3,"file":"pageConfigJson.helpers.js","sourceRoot":"","sources":["../../../../src/ai/tools/helpers/pageConfigJson.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAa,EAAY,EAAE;IAChE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,GAAG;SACP,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,EAAE;IAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,aAAqB,EAAE,KAAa,EAAE,EAAE;IAC5E,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACnC,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACnE,OAAO,eAAe,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAkB,EAAE;IACrE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,QAAQ,GAAI,MAAc,CAAC,QAAQ,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAA4B,EAAE,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,MAAsB,EAAE,EAAE,CAChE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAEtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAA0B,EAAE,EAAE;IAC9D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,MAAM,IAAI,GAAG,CAAC,GAAqB,EAAE,EAAE;QACrC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,SAAS;YAC5C,MAAM,EAAE,GAAI,EAAU,CAAC,EAAE,CAAC;YAC1B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE;gBAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAI,EAAU,CAAC,QAAQ,CAAC;YACtC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAAE,IAAI,CAAC,QAA4B,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,QAA0B,EAC1B,WAAwB,EACxB,EAAE;IACF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,GAAqB,EAAE,EAAE;QACrC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,SAAS;YAE5C,MAAM,KAAK,GAAG,EAAS,CAAC;YACxB,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtC,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;gBAC3C,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC;gBACjB,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC;gBACrB,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,QAA4B,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAA0B,EAC1B,SAAiB,EACM,EAAE;IACzB,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAErB,MAAM,IAAI,GAAG,CAAC,GAAqB,EAAyB,EAAE;QAC5D,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,SAAS;YAC5C,IAAK,EAAU,CAAC,EAAE,KAAK,EAAE;gBAAE,OAAO,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAI,EAAU,CAAC,QAAQ,CAAC;YACtC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,QAA4B,CAAC,CAAC;gBACjD,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAA0B,EAC1B,EAAU,EACD,EAAE;IACX,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAE1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,CAAC,GAAqB,EAAE,EAAE;QACrC,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YAC/C,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAQ,CAAC;YAC3B,IAAI,EAAE,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;gBACtB,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBACnB,OAAO,GAAG,IAAI,CAAC;gBACf,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC;gBAAE,IAAI,CAAC,EAAE,CAAC,QAA4B,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,CAAC;IACf,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAE,OAAe,EAAE,EAAE;IACzE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CACnB,GAAG,EACH,gBAAgB,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAC5E,CAAC;IACF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CACnB,GAAG,EACH,gBAAgB,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAC5E,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhD,sDAAsD;QACtD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC/B,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC/B,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,qDAAqD;gBACrD,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uBAAuB;QACvB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,IASxC,EAAqB,EAAE;IACtB,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IACnC,MAAM,MAAM,GAAG,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACrD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,IAAI,GAAG,KAAK,EAAE,OAAe,EAAE,EAAE;QACrC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QAED,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACvD,aAAa,GAAG,IAAI,CAAC;gBACrB,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxF,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,aAAqB,EAAE,cAAsB,EAAW,EAAE;IACnF,MAAM,QAAQ,GAAG,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;IAEvD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,OAAO,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1B,4CAA4C;QAC5C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,sCAAsC;QACtC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,CAAC;YACP,SAAS;QACX,CAAC;QAED,cAAc;QACd,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7C,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,CAAC;YACP,SAAS;QACX,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0FAA0F;IAC1F,+EAA+E;IAC/E,IAAI,IAAI,KAAK,OAAO,CAAC,MAAM,IAAI,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtD,kFAAkF;QAClF,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC5E,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAC5C,aAAqB,EACrB,KAAa,EACb,EAAU,EACO,EAAE;IACnB,2BAA2B;IAC3B,MAAM,SAAS,GAAG,qBAAqB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;IAED,iDAAiD;IACjD,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;IAElE,+BAA+B;IAC/B,KAAK,MAAM,SAAS,IAAI,SAAS,EAAE,CAAC;QAClC,IAAI,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,qBAAqB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport { createElementId } from \"./elementid.helpers.js\";\nimport { toWorkspacePath } from \"./fileSystem.helpers.js\";\nimport type { CoreFs } from \"../implementations/workspaceDeps.js\";\n\nexport type PageConfigJson = {\n elements: BuilderElement[];\n};\n\nexport const normalizeRouteSegments = (route: string): string[] => {\n const raw = String(route ?? \"\").trim();\n if (!raw || raw === \"/\") return [];\n return raw\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .map((s) => s.trim())\n .filter(Boolean);\n};\n\nexport const isSafeSegment = (segment: string) => {\n const s = String(segment ?? \"\").trim();\n if (!s) return false;\n if (s === \".\" || s === \"..\") return false;\n if (s.includes(\"/\") || s.includes(\"\\\\\")) return false;\n return true;\n};\n\nexport const getPageConfigJsonPath = (workspaceRoot: string, route: string) => {\n const segments = normalizeRouteSegments(route);\n if (segments.some((s) => !isSafeSegment(s))) {\n throw new Error(\"invalid route\");\n }\n const rel = path.posix.join(\"app\", ...segments, \"pageConfig.json\");\n return toWorkspacePath(workspaceRoot, rel);\n};\n\nexport const parsePageConfigJson = (content: string): PageConfigJson => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(String(content ?? \"\"));\n } catch {\n throw new Error(\"pageConfig.json is not valid JSON\");\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"pageConfig.json must be an object\");\n }\n\n const elements = (parsed as any).elements;\n if (!Array.isArray(elements)) {\n throw new Error('pageConfig.json must contain \"elements\" array');\n }\n\n return { elements: elements as BuilderElement[] };\n};\n\nexport const stringifyPageConfigJson = (config: PageConfigJson) =>\n JSON.stringify({ elements: config.elements ?? [] }, null, 2) + \"\\n\";\n\nexport const extractAllIdsDeep = (elements: BuilderElement[]) => {\n const ids = new Set<string>();\n const walk = (arr: BuilderElement[]) => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n const id = (el as any).id;\n if (typeof id === \"string\" && id.trim()) ids.add(id.trim());\n const children = (el as any).children;\n if (Array.isArray(children)) walk(children as BuilderElement[]);\n }\n };\n walk(Array.isArray(elements) ? elements : []);\n return ids;\n};\n\nexport const ensureElementIds = (\n elements: BuilderElement[],\n existingIds: Set<string>,\n) => {\n const seen = new Set<string>();\n const walk = (arr: BuilderElement[]) => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n\n const anyEl = el as any;\n const currentId = typeof anyEl.id === \"string\" ? anyEl.id.trim() : \"\";\n if (!currentId || seen.has(currentId)) {\n const newId = createElementId(existingIds);\n anyEl.id = newId;\n existingIds.add(newId);\n seen.add(newId);\n } else {\n anyEl.id = currentId;\n existingIds.add(currentId);\n seen.add(currentId);\n }\n\n if (Array.isArray(anyEl.children)) {\n walk(anyEl.children as BuilderElement[]);\n }\n }\n };\n walk(elements);\n};\n\nexport const findElementById = (\n elements: BuilderElement[],\n elementId: string,\n): BuilderElement | null => {\n const id = String(elementId ?? \"\").trim();\n if (!id) return null;\n\n const walk = (arr: BuilderElement[]): BuilderElement | null => {\n for (const el of arr) {\n if (!el || typeof el !== \"object\") continue;\n if ((el as any).id === id) return el;\n const children = (el as any).children;\n if (Array.isArray(children)) {\n const found = walk(children as BuilderElement[]);\n if (found) return found;\n }\n }\n return null;\n };\n\n return walk(elements);\n};\n\nexport const deleteElementById = (\n elements: BuilderElement[],\n id: string,\n): boolean => {\n const target = String(id ?? \"\").trim();\n if (!target) return false;\n\n let deleted = false;\n const walk = (arr: BuilderElement[]) => {\n for (let idx = arr.length - 1; idx >= 0; idx--) {\n const el = arr[idx] as any;\n if (el?.id === target) {\n arr.splice(idx, 1);\n deleted = true;\n continue;\n }\n if (Array.isArray(el?.children)) walk(el.children as BuilderElement[]);\n }\n };\n walk(elements);\n return deleted;\n};\n\nexport const writeFileAtomic = async (filePath: string, content: string) => {\n const dir = path.dirname(filePath);\n const base = path.basename(filePath);\n const tmp = path.join(\n dir,\n `.qwintly_tmp_${base}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n const bak = path.join(\n dir,\n `.qwintly_bak_${base}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n try {\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(tmp, content ?? \"\", \"utf-8\");\n\n // Windows rename doesn't overwrite; do a 2-step swap.\n try {\n await fs.rename(filePath, bak);\n await fs.rename(tmp, filePath);\n await fs.rm(bak, { force: true });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n // No previous file; just put the temp file in place.\n await fs.rename(tmp, filePath);\n } else {\n throw err;\n }\n }\n } catch (err) {\n // rollback best-effort\n try {\n await fs.rm(tmp, { force: true });\n } catch {\n // ignore\n }\n try {\n await fs.stat(bak);\n try {\n await fs.rm(filePath, { force: true });\n } catch {\n // ignore\n }\n await fs.rename(bak, filePath);\n } catch {\n // ignore\n }\n throw err;\n }\n};\n\nexport const getAvailableRoutes = async (deps: {\n workspaceRoot: string;\n fs: {\n safeReadDir: (absoluteDir: string) => Promise<Array<{\n name: string;\n isDirectory: () => boolean;\n isFile: () => boolean;\n }>>;\n };\n}): Promise<string[]> => {\n const { workspaceRoot, fs } = deps;\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n const routes: string[] = [];\n\n const scan = async (dirPath: string) => {\n let entries;\n try {\n entries = await fs.safeReadDir(dirPath);\n } catch {\n return;\n }\n\n let hasPageConfig = false;\n for (const entry of entries) {\n if (entry.isFile() && entry.name === \"pageConfig.json\") {\n hasPageConfig = true;\n break;\n }\n }\n\n if (hasPageConfig) {\n const rel = path.relative(appDir, dirPath);\n const routeStr = \"/\" + rel.replace(/\\\\/g, \"/\");\n routes.push(routeStr === \"/\" ? \"/\" : routeStr.replace(/\\/$/, \"\"));\n }\n\n for (const entry of entries) {\n if (entry.isDirectory() && entry.name !== \"node_modules\" && !entry.name.startsWith(\".\")) {\n await scan(path.join(dirPath, entry.name));\n }\n }\n };\n\n await scan(appDir);\n return routes.sort();\n};\n\nexport const matchRoute = (physicalRoute: string, requestedRoute: string): boolean => {\n const physSegs = normalizeRouteSegments(physicalRoute);\n const reqSegs = normalizeRouteSegments(requestedRoute);\n\n let pIdx = 0;\n let rIdx = 0;\n\n while (pIdx < physSegs.length && rIdx < reqSegs.length) {\n const phys = physSegs[pIdx];\n const req = reqSegs[rIdx];\n\n // Catch-all (e.g. [...slug] or [[...slug]])\n if (phys.startsWith(\"[\") && phys.endsWith(\"]\") && phys.includes(\"...\")) {\n return true;\n }\n\n // Regular dynamic segment (e.g. [id])\n if (phys.startsWith(\"[\") && phys.endsWith(\"]\")) {\n pIdx++;\n rIdx++;\n continue;\n }\n\n // Exact match\n if (phys.toLowerCase() === req.toLowerCase()) {\n pIdx++;\n rIdx++;\n continue;\n }\n\n return false;\n }\n\n // Handle case where we ran out of requested segments but have remaining physical segments\n // e.g. physical is /blog/[[...slug]] (optional catch-all) and request is /blog\n if (rIdx === reqSegs.length && pIdx < physSegs.length) {\n // All remaining physical segments must be optional catch-alls (e.g., [[...slug]])\n for (let i = pIdx; i < physSegs.length; i++) {\n const phys = physSegs[i];\n if (!(phys.startsWith(\"[[\") && phys.endsWith(\"]]\") && phys.includes(\"...\"))) {\n return false;\n }\n }\n return true;\n }\n\n return pIdx === physSegs.length && rIdx === reqSegs.length;\n};\n\nexport const resolvePageConfigJsonPath = async (\n workspaceRoot: string,\n route: string,\n fs: CoreFs,\n): Promise<string> => {\n // 1. Try exact match first\n const exactPath = getPageConfigJsonPath(workspaceRoot, route);\n try {\n await fs.stat(exactPath);\n return exactPath;\n } catch {\n // Exact file does not exist, let's resolve dynamically\n }\n\n // 2. Fetch all available routes in the workspace\n const available = await getAvailableRoutes({ workspaceRoot, fs });\n\n // 3. Find first matching route\n for (const physRoute of available) {\n if (matchRoute(physRoute, route)) {\n return getPageConfigJsonPath(workspaceRoot, physRoute);\n }\n }\n\n // 4. Fallback: if no match, just return the exact path\n return exactPath;\n};\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"createNewRoute.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA0CxD,eAAO,MAAM,wBAAwB,GAAI,MAAM,aAAa,MAG5C,aAAa,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;EAgJrD,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAsB,CAAC;AAC5D,eAAO,MAAM,wBAAwB,QAAoB,CAAC"}
1
+ {"version":3,"file":"createNewRoute.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA0CxD,eAAO,MAAM,wBAAwB,GAAI,MAAM,aAAa,MAG5C,aAAa,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;EA8JrD,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAsB,CAAC;AAC5D,eAAO,MAAM,wBAAwB,QAAoB,CAAC"}
@@ -33,7 +33,7 @@ const DEFAULT_PAGE_CONFIG = (() => {
33
33
  export const createCreateNewRouteImpl = (deps) => {
34
34
  const { workspaceRoot, fs: coreFs } = deps;
35
35
  return async (parentRoute, routeName) => {
36
- const parentSegments = normalizeRouteSegments(parentRoute);
36
+ let parentSegments = normalizeRouteSegments(parentRoute);
37
37
  const routeSegment = String(routeName ?? "").trim();
38
38
  if (!isSafeSegment(routeSegment)) {
39
39
  return {
@@ -41,38 +41,42 @@ export const createCreateNewRouteImpl = (deps) => {
41
41
  error: "Invalid route name",
42
42
  };
43
43
  }
44
+ // Check if the parentRoute is proper (all segments are safe).
45
+ // If not proper, create the new route under the '/' route.
44
46
  if (parentSegments.some((s) => !isSafeSegment(s))) {
45
- return {
46
- success: false,
47
- error: "Invalid parent route",
48
- };
47
+ parentSegments = [];
49
48
  }
50
49
  const appDir = toWorkspacePath(workspaceRoot, "app");
51
- const parentDir = path.join(appDir, ...parentSegments);
52
- const finalDir = path.join(parentDir, routeSegment);
53
- // Parent must exist (don't implicitly create arbitrary routes).
50
+ const ensureRouteExists = async (segments) => {
51
+ const parentDir = path.join(appDir, ...segments.slice(0, -1));
52
+ const seg = segments[segments.length - 1];
53
+ const finalDir = path.join(parentDir, seg);
54
+ try {
55
+ const st = await coreFs.stat(finalDir);
56
+ if (st.isDirectory()) {
57
+ return;
58
+ }
59
+ }
60
+ catch { }
61
+ const tmpDir = path.join(parentDir, `.qwintly_route_tmp_${seg}_${Date.now()}_${Math.random().toString(16).slice(2)}`);
62
+ await coreFs.mkdirp(tmpDir);
63
+ await coreFs.writeFile(path.join(tmpDir, "page.tsx"), PAGE_TSX_TEMPLATE);
64
+ await coreFs.writeFile(path.join(tmpDir, "pageConfig.json"), DEFAULT_PAGE_CONFIG);
65
+ await fs.rename(tmpDir, finalDir);
66
+ };
54
67
  try {
55
- const st = await coreFs.stat(parentDir);
56
- if (!st.isDirectory()) {
57
- return {
58
- success: false,
59
- error: "Parent not a folder",
60
- };
68
+ for (let i = 1; i <= parentSegments.length; i++) {
69
+ await ensureRouteExists(parentSegments.slice(0, i));
61
70
  }
62
71
  }
63
72
  catch (err) {
64
- const code = err?.code;
65
- if (code === "ENOENT") {
66
- return {
67
- success: false,
68
- error: "Parent route missing",
69
- };
70
- }
71
73
  return {
72
74
  success: false,
73
- error: "Parent check failed",
75
+ error: `Failed to ensure parent route: ${err instanceof Error ? err.message : String(err)}`,
74
76
  };
75
77
  }
78
+ const parentDir = path.join(appDir, ...parentSegments);
79
+ const finalDir = path.join(parentDir, routeSegment);
76
80
  // Route must not already exist.
77
81
  try {
78
82
  await coreFs.stat(finalDir);