@vedangiitb/qwintly-core 1.4.12 → 1.4.13

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 (142) hide show
  1. package/dist/ai/generate/gemini.client.js +1 -1
  2. package/dist/ai/generate/gemini.client.js.map +1 -1
  3. package/dist/ai/generate/generateClient.d.ts.map +1 -1
  4. package/dist/ai/generate/generateClient.js +7 -3
  5. package/dist/ai/generate/generateClient.js.map +1 -1
  6. package/dist/ai/toolLoop/helpers/aiCall.helper.d.ts +16 -0
  7. package/dist/ai/toolLoop/helpers/aiCall.helper.d.ts.map +1 -0
  8. package/dist/ai/toolLoop/helpers/aiCall.helper.js +23 -0
  9. package/dist/ai/toolLoop/helpers/aiCall.helper.js.map +1 -0
  10. package/dist/ai/toolLoop/helpers/applyPatch.helper.d.ts +6 -0
  11. package/dist/ai/toolLoop/helpers/applyPatch.helper.d.ts.map +1 -0
  12. package/dist/ai/toolLoop/helpers/applyPatch.helper.js +10 -0
  13. package/dist/ai/toolLoop/helpers/applyPatch.helper.js.map +1 -0
  14. package/dist/ai/toolLoop/helpers/errors.helper.d.ts +15 -0
  15. package/dist/ai/toolLoop/helpers/errors.helper.d.ts.map +1 -0
  16. package/dist/ai/toolLoop/helpers/errors.helper.js +50 -0
  17. package/dist/ai/toolLoop/helpers/errors.helper.js.map +1 -0
  18. package/dist/ai/toolLoop/helpers/fsHelpers.d.ts +5 -0
  19. package/dist/ai/toolLoop/helpers/fsHelpers.d.ts.map +1 -0
  20. package/dist/ai/toolLoop/helpers/fsHelpers.js +28 -0
  21. package/dist/ai/toolLoop/helpers/fsHelpers.js.map +1 -0
  22. package/dist/ai/toolLoop/helpers/patchRetry.helper.d.ts +11 -0
  23. package/dist/ai/toolLoop/helpers/patchRetry.helper.d.ts.map +1 -0
  24. package/dist/ai/toolLoop/helpers/patchRetry.helper.js +30 -0
  25. package/dist/ai/toolLoop/helpers/patchRetry.helper.js.map +1 -0
  26. package/dist/ai/toolLoop/helpers/persistTokens.helpers.d.ts +7 -0
  27. package/dist/ai/toolLoop/helpers/persistTokens.helpers.d.ts.map +1 -0
  28. package/dist/ai/toolLoop/helpers/persistTokens.helpers.js +25 -0
  29. package/dist/ai/toolLoop/helpers/persistTokens.helpers.js.map +1 -0
  30. package/dist/ai/toolLoop/{plannerTaskParser.d.ts → helpers/plannerTaskParser.d.ts} +1 -1
  31. package/dist/ai/toolLoop/helpers/plannerTaskParser.d.ts.map +1 -0
  32. package/dist/ai/toolLoop/helpers/plannerTaskParser.js.map +1 -0
  33. package/dist/ai/toolLoop/helpers/readFile.helpers.d.ts +10 -0
  34. package/dist/ai/toolLoop/helpers/readFile.helpers.d.ts.map +1 -0
  35. package/dist/ai/toolLoop/helpers/readFile.helpers.js +26 -0
  36. package/dist/ai/toolLoop/helpers/readFile.helpers.js.map +1 -0
  37. package/dist/ai/toolLoop/helpers/signatures.helper.d.ts +2 -0
  38. package/dist/ai/toolLoop/helpers/signatures.helper.d.ts.map +1 -0
  39. package/dist/ai/toolLoop/helpers/signatures.helper.js +23 -0
  40. package/dist/ai/toolLoop/helpers/signatures.helper.js.map +1 -0
  41. package/dist/ai/toolLoop/helpers/toolArgs.helper.d.ts +12 -0
  42. package/dist/ai/toolLoop/helpers/toolArgs.helper.d.ts.map +1 -0
  43. package/dist/ai/toolLoop/helpers/toolArgs.helper.js +40 -0
  44. package/dist/ai/toolLoop/helpers/toolArgs.helper.js.map +1 -0
  45. package/dist/ai/toolLoop/helpers/toolExecution.helper.d.ts +22 -0
  46. package/dist/ai/toolLoop/helpers/toolExecution.helper.d.ts.map +1 -0
  47. package/dist/ai/toolLoop/helpers/toolExecution.helper.js +75 -0
  48. package/dist/ai/toolLoop/helpers/toolExecution.helper.js.map +1 -0
  49. package/dist/ai/toolLoop/helpers/toolHandlers.helper.d.ts +6 -0
  50. package/dist/ai/toolLoop/helpers/toolHandlers.helper.d.ts.map +1 -0
  51. package/dist/ai/toolLoop/helpers/toolHandlers.helper.js +86 -0
  52. package/dist/ai/toolLoop/helpers/toolHandlers.helper.js.map +1 -0
  53. package/dist/ai/toolLoop/toolEventSummary.d.ts +28 -0
  54. package/dist/ai/toolLoop/toolEventSummary.d.ts.map +1 -0
  55. package/dist/ai/toolLoop/toolEventSummary.js +253 -0
  56. package/dist/ai/toolLoop/toolEventSummary.js.map +1 -0
  57. package/dist/ai/toolLoop/toolLoopContext.d.ts +0 -14
  58. package/dist/ai/toolLoop/toolLoopContext.d.ts.map +1 -1
  59. package/dist/ai/toolLoop/toolLoopContext.js +7 -50
  60. package/dist/ai/toolLoop/toolLoopContext.js.map +1 -1
  61. package/dist/ai/toolLoop/toolLoopRunner.d.ts +6 -5
  62. package/dist/ai/toolLoop/toolLoopRunner.d.ts.map +1 -1
  63. package/dist/ai/toolLoop/toolLoopRunner.js +48 -281
  64. package/dist/ai/toolLoop/toolLoopRunner.js.map +1 -1
  65. package/dist/ai/toolLoop/toolStatusMessage.d.ts +6 -0
  66. package/dist/ai/toolLoop/toolStatusMessage.d.ts.map +1 -0
  67. package/dist/ai/toolLoop/toolStatusMessage.js +140 -0
  68. package/dist/ai/toolLoop/toolStatusMessage.js.map +1 -0
  69. package/dist/ai/tools/helpers/applyPatch.helpers.d.ts.map +1 -1
  70. package/dist/ai/tools/helpers/applyPatch.helpers.js +9 -4
  71. package/dist/ai/tools/helpers/applyPatch.helpers.js.map +1 -1
  72. package/dist/ai/tools/helpers/fileSystem.helpers.d.ts.map +1 -1
  73. package/dist/ai/tools/helpers/fileSystem.helpers.js +7 -1
  74. package/dist/ai/tools/helpers/fileSystem.helpers.js.map +1 -1
  75. package/dist/ai/tools/helpers/pageConfigJson.helpers.d.ts +13 -0
  76. package/dist/ai/tools/helpers/pageConfigJson.helpers.d.ts.map +1 -1
  77. package/dist/ai/tools/helpers/pageConfigJson.helpers.js +51 -21
  78. package/dist/ai/tools/helpers/pageConfigJson.helpers.js.map +1 -1
  79. package/dist/ai/tools/implementations/applyPatch.impl.js +2 -2
  80. package/dist/ai/tools/implementations/applyPatch.impl.js.map +1 -1
  81. package/dist/ai/tools/implementations/createNewRoute.impl.js +1 -1
  82. package/dist/ai/tools/implementations/createNewRoute.impl.js.map +1 -1
  83. package/dist/ai/tools/implementations/deleteElement.impl.d.ts.map +1 -1
  84. package/dist/ai/tools/implementations/deleteElement.impl.js +5 -37
  85. package/dist/ai/tools/implementations/deleteElement.impl.js.map +1 -1
  86. package/dist/ai/tools/implementations/insertElement.impl.d.ts.map +1 -1
  87. package/dist/ai/tools/implementations/insertElement.impl.js +9 -46
  88. package/dist/ai/tools/implementations/insertElement.impl.js.map +1 -1
  89. package/dist/ai/tools/implementations/updateClassName.impl.d.ts.map +1 -1
  90. package/dist/ai/tools/implementations/updateClassName.impl.js +5 -37
  91. package/dist/ai/tools/implementations/updateClassName.impl.js.map +1 -1
  92. package/dist/ai/tools/implementations/updateGlobalStyles.impl.d.ts.map +1 -1
  93. package/dist/ai/tools/implementations/updateGlobalStyles.impl.js +4 -3
  94. package/dist/ai/tools/implementations/updateGlobalStyles.impl.js.map +1 -1
  95. package/dist/ai/tools/implementations/updateProps.impl.d.ts.map +1 -1
  96. package/dist/ai/tools/implementations/updateProps.impl.js +5 -37
  97. package/dist/ai/tools/implementations/updateProps.impl.js.map +1 -1
  98. package/dist/ai/tools/schemas/createNewRoute.schema.d.ts.map +1 -1
  99. package/dist/ai/tools/schemas/createNewRoute.schema.js +1 -1
  100. package/dist/ai/tools/schemas/createNewRoute.schema.js.map +1 -1
  101. package/dist/ai/tools/schemas/deleteElement.schema.d.ts.map +1 -1
  102. package/dist/ai/tools/schemas/deleteElement.schema.js +1 -2
  103. package/dist/ai/tools/schemas/deleteElement.schema.js.map +1 -1
  104. package/dist/ai/tools/schemas/elementProps.schema.d.ts +101 -0
  105. package/dist/ai/tools/schemas/elementProps.schema.d.ts.map +1 -0
  106. package/dist/ai/tools/schemas/elementProps.schema.js +74 -0
  107. package/dist/ai/tools/schemas/elementProps.schema.js.map +1 -0
  108. package/dist/ai/tools/schemas/insertElement.schema.d.ts.map +1 -1
  109. package/dist/ai/tools/schemas/insertElement.schema.js +2 -74
  110. package/dist/ai/tools/schemas/insertElement.schema.js.map +1 -1
  111. package/dist/ai/tools/schemas/updateClassName.schema.d.ts.map +1 -1
  112. package/dist/ai/tools/schemas/updateClassName.schema.js +1 -2
  113. package/dist/ai/tools/schemas/updateClassName.schema.js.map +1 -1
  114. package/dist/ai/tools/schemas/updateProps.schema.d.ts +9 -9
  115. package/dist/ai/tools/schemas/updateProps.schema.d.ts.map +1 -1
  116. package/dist/ai/tools/schemas/updateProps.schema.js +3 -69
  117. package/dist/ai/tools/schemas/updateProps.schema.js.map +1 -1
  118. package/dist/image/unsplash.service.d.ts.map +1 -1
  119. package/dist/image/unsplash.service.js +6 -2
  120. package/dist/image/unsplash.service.js.map +1 -1
  121. package/dist/indexer/projectInfoIndex.d.ts.map +1 -1
  122. package/dist/indexer/projectInfoIndex.js +33 -25
  123. package/dist/indexer/projectInfoIndex.js.map +1 -1
  124. package/dist/types/styleConfig.d.ts.map +1 -1
  125. package/dist/types/styleConfig.js +2 -3
  126. package/dist/types/styleConfig.js.map +1 -1
  127. package/dist/utils/utils.d.ts +3 -0
  128. package/dist/utils/utils.d.ts.map +1 -1
  129. package/dist/utils/utils.js +8 -0
  130. package/dist/utils/utils.js.map +1 -1
  131. package/dist/utils/workspace.d.ts +1 -1
  132. package/dist/utils/workspace.d.ts.map +1 -1
  133. package/dist/utils/workspace.js +6 -11
  134. package/dist/utils/workspace.js.map +1 -1
  135. package/package.json +1 -1
  136. package/dist/ai/toolLoop/plannerTaskParser.d.ts.map +0 -1
  137. package/dist/ai/toolLoop/plannerTaskParser.js.map +0 -1
  138. package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts +0 -51
  139. package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts.map +0 -1
  140. package/dist/ai/toolLoop/toolLoopRunnerUtils.js +0 -367
  141. package/dist/ai/toolLoop/toolLoopRunnerUtils.js.map +0 -1
  142. /package/dist/ai/toolLoop/{plannerTaskParser.js → helpers/plannerTaskParser.js} +0 -0
@@ -212,8 +212,11 @@ export const getAvailableRoutes = async (deps) => {
212
212
  }
213
213
  };
214
214
  await scan(appDir);
215
- return routes.sort();
215
+ return routes.sort((a, b) => a.localeCompare(b));
216
216
  };
217
+ const isCatchAll = (segment) => segment.startsWith("[") && segment.endsWith("]") && segment.includes("...");
218
+ const isDynamic = (segment) => segment.startsWith("[") && segment.endsWith("]");
219
+ const isOptionalCatchAll = (segment) => segment.startsWith("[[") && segment.endsWith("]]") && segment.includes("...");
217
220
  export const matchRoute = (physicalRoute, requestedRoute) => {
218
221
  const physSegs = normalizeRouteSegments(physicalRoute);
219
222
  const reqSegs = normalizeRouteSegments(requestedRoute);
@@ -222,35 +225,18 @@ export const matchRoute = (physicalRoute, requestedRoute) => {
222
225
  while (pIdx < physSegs.length && rIdx < reqSegs.length) {
223
226
  const phys = physSegs[pIdx];
224
227
  const req = reqSegs[rIdx];
225
- // Catch-all (e.g. [...slug] or [[...slug]])
226
- if (phys.startsWith("[") && phys.endsWith("]") && phys.includes("...")) {
228
+ if (isCatchAll(phys)) {
227
229
  return true;
228
230
  }
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()) {
231
+ if (isDynamic(phys) || phys.toLowerCase() === req.toLowerCase()) {
237
232
  pIdx++;
238
233
  rIdx++;
239
234
  continue;
240
235
  }
241
236
  return false;
242
237
  }
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
238
  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;
239
+ return physSegs.slice(pIdx).every(isOptionalCatchAll);
254
240
  }
255
241
  return pIdx === physSegs.length && rIdx === reqSegs.length;
256
242
  };
@@ -275,4 +261,48 @@ export const resolvePageConfigJsonPath = async (workspaceRoot, route, fs) => {
275
261
  // 4. Fallback: if no match, just return the exact path
276
262
  return exactPath;
277
263
  };
264
+ export const loadAndPreparePageConfig = async (workspaceRoot, route, fs) => {
265
+ let configPath;
266
+ try {
267
+ configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);
268
+ }
269
+ catch (err) {
270
+ return {
271
+ success: false,
272
+ error: err instanceof Error ? err.message : String(err),
273
+ };
274
+ }
275
+ let before = "";
276
+ try {
277
+ before = await fs.readFile(configPath);
278
+ }
279
+ catch (err) {
280
+ const code = err?.code;
281
+ if (code === "ENOENT")
282
+ return { success: false, error: "not found" };
283
+ return {
284
+ success: false,
285
+ error: err instanceof Error ? err.message : String(err),
286
+ };
287
+ }
288
+ let parsed;
289
+ try {
290
+ parsed = parsePageConfigJson(before);
291
+ }
292
+ catch (err) {
293
+ return {
294
+ success: false,
295
+ error: err instanceof Error ? err.message : String(err),
296
+ };
297
+ }
298
+ const elements = parsed.elements ?? [];
299
+ const existingIds = extractAllIdsDeep(elements);
300
+ ensureElementIds(elements, existingIds);
301
+ return {
302
+ success: true,
303
+ configPath,
304
+ elements,
305
+ existingIds,
306
+ };
307
+ };
278
308
  //# 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\";\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
+ {"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\";\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((a, b) => a.localeCompare(b));\n};\n\nconst isCatchAll = (segment: string): boolean =>\n segment.startsWith(\"[\") && segment.endsWith(\"]\") && segment.includes(\"...\");\n\nconst isDynamic = (segment: string): boolean =>\n segment.startsWith(\"[\") && segment.endsWith(\"]\");\n\nconst isOptionalCatchAll = (segment: string): boolean =>\n segment.startsWith(\"[[\") && segment.endsWith(\"]]\") && segment.includes(\"...\");\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 if (isCatchAll(phys)) {\n return true;\n }\n\n if (isDynamic(phys) || phys.toLowerCase() === req.toLowerCase()) {\n pIdx++;\n rIdx++;\n continue;\n }\n\n return false;\n }\n\n if (rIdx === reqSegs.length && pIdx < physSegs.length) {\n return physSegs.slice(pIdx).every(isOptionalCatchAll);\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\nexport const loadAndPreparePageConfig = async (\n workspaceRoot: string,\n route: string,\n fs: CoreFs,\n) => {\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);\n } catch (err) {\n return {\n success: false as const,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false as const, error: \"not found\" };\n return {\n success: false as const,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false as const,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n return {\n success: true as const,\n configPath,\n elements,\n existingIds,\n };\n};\n\n\n"]}
@@ -41,8 +41,8 @@ export const createApplyPatchImpl = (deps) => {
41
41
  const seen = new Set();
42
42
  const normalized = (patch ?? "").replace(/\r\n/g, "\n");
43
43
  for (const line of normalized.split("\n")) {
44
- const match = /^\*\*\* (Update File|Add File|Delete File):\s+(.+)$/.exec(line.trim()) ??
45
- /^\*\*\* Move to:\s+(.+)$/.exec(line.trim());
44
+ const match = /^\*\*\* (Update File|Add File|Delete File):\s+(\S.*)$/.exec(line.trim()) ??
45
+ /^\*\*\* Move to:\s+(\S.*)$/.exec(line.trim());
46
46
  if (!match)
47
47
  continue;
48
48
  const p = (match[2] ?? match[1] ?? "").trim();
@@ -1 +1 @@
1
- {"version":3,"file":"applyPatch.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/applyPatch.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { applyHunksToContent, isTextFilePath, parseApplyPatch } from \"../helpers/applyPatch.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isAllowedRouteFilePath,\n isPageTsxPath,\n matchesPageTsxTemplate,\n normalizeFsPathForPolicy,\n PAGE_TSX_TEMPLATE,\n} from \"../helpers/nextRouteFilePolicy.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createApplyPatchImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (patchString: string) => {\n let parsedOps: ReturnType<typeof parseApplyPatch> | null = null;\n const debugFiles: Array<{ path: string; head: string }> = [];\n\n const HEAD_MAX_LINES = 80;\n\n const headLines = (content: string) =>\n content.replace(/\\r\\n/g, \"\\n\").split(\"\\n\").slice(0, HEAD_MAX_LINES).join(\"\\n\");\n\n const addDebugSnapshot = async (filePath: string, label?: string) => {\n if (!filePath) return;\n if (debugFiles.length >= 3) return;\n if (debugFiles.some((f) => f.path === filePath)) return;\n\n try {\n const absolute = toWorkspacePath(workspaceRoot, filePath);\n try {\n await fs.stat(absolute);\n const content = await fs.readFile(absolute);\n debugFiles.push({\n path: filePath,\n head: `${label ? `${label}\\n` : \"\"}${headLines(content)}`,\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n const suffix = code === \"ENOENT\" ? \"(not found)\" : \"(unreadable)\";\n debugFiles.push({ path: filePath, head: `${label ? `${label} ` : \"\"}${suffix}` });\n }\n } catch {\n debugFiles.push({ path: filePath, head: `${label ? `${label} ` : \"\"}(invalid path)` });\n }\n };\n\n const extractPatchPaths = (patch: string) => {\n const out: string[] = [];\n const seen = new Set<string>();\n const normalized = (patch ?? \"\").replace(/\\r\\n/g, \"\\n\");\n for (const line of normalized.split(\"\\n\")) {\n const match =\n /^\\*\\*\\* (Update File|Add File|Delete File):\\s+(.+)$/.exec(line.trim()) ??\n /^\\*\\*\\* Move to:\\s+(.+)$/.exec(line.trim());\n if (!match) continue;\n const p = (match[2] ?? match[1] ?? \"\").trim();\n if (!p || seen.has(p)) continue;\n seen.add(p);\n out.push(p);\n if (out.length >= 10) break;\n }\n return out;\n };\n\n try {\n const operations = parseApplyPatch(patchString);\n parsedOps = operations;\n\n for (const op of operations) {\n const opPath = normalizeFsPathForPolicy(op.filePath);\n if (!isAllowedRouteFilePath(opPath)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: only route files named \"page.tsx\" or \"page.config.ts\" may be modified.\\n` +\n `Found operation on: \"${opPath}\"`,\n allowed: Array.from([\"page.tsx\", \"page.config.ts\"]),\n };\n }\n\n if (op.kind === \"update\" && op.moveTo && op.moveTo !== op.filePath) {\n const moveToPath = normalizeFsPathForPolicy(op.moveTo);\n if (!isAllowedRouteFilePath(moveToPath)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: move target must be a route file named \"page.tsx\" or \"page.config.ts\".\\n` +\n `From: \"${opPath}\"\\n` +\n `To: \"${moveToPath}\"`,\n allowed: Array.from([\"page.tsx\", \"page.config.ts\"]),\n };\n }\n\n const fromName = opPath.split(\"/\").pop() ?? \"\";\n const toName = moveToPath.split(\"/\").pop() ?? \"\";\n if (fromName !== toName) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: renaming between route file types is not allowed.\\n` +\n `From: \"${opPath}\"\\n` +\n `To: \"${moveToPath}\"`,\n };\n }\n }\n\n if (isPageTsxPath(opPath)) {\n if (op.kind === \"update\") {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: updates to \"page.tsx\" are not allowed for any route. ` +\n `Only Add File (create) or Delete File is allowed.\\n` +\n `Path: \"${opPath}\"`,\n rule: \"page.tsx is immutable after creation\",\n };\n }\n\n if (op.kind === \"add\") {\n const { content: after } = applyHunksToContent(\"\", op.hunks);\n if (!matchesPageTsxTemplate(after)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: new \"page.tsx\" must match the exact required template (byte-for-byte).\\n` +\n `Path: \"${opPath}\"\\n` +\n `Expected:\\n${PAGE_TSX_TEMPLATE}`,\n rule: \"page.tsx must match template on creation\",\n };\n }\n }\n }\n }\n\n let changed = false;\n const warnings: string[] = [];\n\n for (const op of operations) {\n if (!isTextFilePath(op.filePath)) {\n throw new Error(`Binary or unsupported file type in patch: \"${op.filePath}\"`);\n }\n if (op.kind === \"update\" && op.moveTo && !isTextFilePath(op.moveTo)) {\n throw new Error(`Binary or unsupported file type in patch: \"${op.moveTo}\"`);\n }\n\n const fullPath = toWorkspacePath(workspaceRoot, op.filePath);\n\n if (op.kind === \"delete\") {\n console.log(\"Tool apply_patch (delete)\", { path: fullPath });\n try {\n await fs.rmFile(fullPath);\n changed = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Delete File failed for \"${op.filePath}\": ${message}`);\n }\n continue;\n }\n\n if (op.kind === \"add\") {\n console.log(\"Tool apply_patch (add)\", { path: fullPath });\n try {\n const { content: after, changed: opChanged } = applyHunksToContent(\n \"\",\n op.hunks,\n );\n await fs.mkdirp(path.dirname(fullPath));\n await fs.writeFile(fullPath, after);\n if (!opChanged) warnings.push(`Add File produced no changes for \"${op.filePath}\".`);\n changed = changed || opChanged;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Add File failed for \"${op.filePath}\": ${message}`);\n }\n continue;\n }\n\n if (op.kind === \"update\") {\n console.log(\"Tool apply_patch (update)\", { path: fullPath });\n try {\n try {\n await fs.stat(fullPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n throw new Error(`\"${op.filePath}\" not found.`);\n }\n throw err;\n }\n\n const before = await fs.readFile(fullPath);\n await addDebugSnapshot(op.filePath, `BEFORE (${op.filePath}):`);\n\n const { content: after, changed: contentChanged } = applyHunksToContent(\n before,\n op.hunks,\n );\n\n if (op.moveTo && op.moveTo !== op.filePath) {\n const moveToPath = toWorkspacePath(workspaceRoot, op.moveTo);\n console.log(\"Tool apply_patch (move)\", {\n from: fullPath,\n to: moveToPath,\n });\n await fs.mkdirp(path.dirname(moveToPath));\n await fs.writeFile(moveToPath, after);\n await fs.rmFile(fullPath);\n changed = true;\n continue;\n }\n\n if (!contentChanged) {\n warnings.push(`Update File made no changes for \"${op.filePath}\".`);\n continue;\n }\n\n await fs.mkdirp(path.dirname(fullPath));\n await fs.writeFile(fullPath, after);\n changed = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Update File failed for \"${op.filePath}\": ${message}`);\n }\n }\n }\n\n return { success: true, changed, warnings: warnings.length > 0 ? warnings : undefined };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\"Tool apply_patch failed\", err, { message });\n\n try {\n if (debugFiles.length < 3) {\n const paths = parsedOps\n ? parsedOps.flatMap((op) =>\n op.kind === \"update\" && op.moveTo\n ? [op.filePath, op.moveTo]\n : [op.filePath],\n )\n : extractPatchPaths(patchString);\n\n for (const p of paths) {\n if (debugFiles.length >= 3) break;\n await addDebugSnapshot(p);\n }\n\n if (debugFiles.length < 3 && parsedOps) {\n for (const op of parsedOps) {\n if (debugFiles.length >= 3) break;\n if (op.kind === \"add\") debugFiles.push({ path: op.filePath, head: \"(new file)\" });\n if (op.kind === \"delete\") debugFiles.push({ path: op.filePath, head: \"(deleted)\" });\n }\n }\n }\n } catch {\n // best-effort only\n }\n\n return {\n success: false,\n error: message,\n debug: debugFiles.length > 0 ? { files: debugFiles.slice(0, 3) } : undefined,\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"applyPatch.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/applyPatch.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { applyHunksToContent, isTextFilePath, parseApplyPatch } from \"../helpers/applyPatch.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isAllowedRouteFilePath,\n isPageTsxPath,\n matchesPageTsxTemplate,\n normalizeFsPathForPolicy,\n PAGE_TSX_TEMPLATE,\n} from \"../helpers/nextRouteFilePolicy.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createApplyPatchImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (patchString: string) => {\n let parsedOps: ReturnType<typeof parseApplyPatch> | null = null;\n const debugFiles: Array<{ path: string; head: string }> = [];\n\n const HEAD_MAX_LINES = 80;\n\n const headLines = (content: string) =>\n content.replace(/\\r\\n/g, \"\\n\").split(\"\\n\").slice(0, HEAD_MAX_LINES).join(\"\\n\");\n\n const addDebugSnapshot = async (filePath: string, label?: string) => {\n if (!filePath) return;\n if (debugFiles.length >= 3) return;\n if (debugFiles.some((f) => f.path === filePath)) return;\n\n try {\n const absolute = toWorkspacePath(workspaceRoot, filePath);\n try {\n await fs.stat(absolute);\n const content = await fs.readFile(absolute);\n debugFiles.push({\n path: filePath,\n head: `${label ? `${label}\\n` : \"\"}${headLines(content)}`,\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n const suffix = code === \"ENOENT\" ? \"(not found)\" : \"(unreadable)\";\n debugFiles.push({ path: filePath, head: `${label ? `${label} ` : \"\"}${suffix}` });\n }\n } catch {\n debugFiles.push({ path: filePath, head: `${label ? `${label} ` : \"\"}(invalid path)` });\n }\n };\n\n const extractPatchPaths = (patch: string) => {\n const out: string[] = [];\n const seen = new Set<string>();\n const normalized = (patch ?? \"\").replace(/\\r\\n/g, \"\\n\");\n for (const line of normalized.split(\"\\n\")) {\n const match =\n /^\\*\\*\\* (Update File|Add File|Delete File):\\s+(\\S.*)$/.exec(line.trim()) ??\n /^\\*\\*\\* Move to:\\s+(\\S.*)$/.exec(line.trim());\n if (!match) continue;\n const p = (match[2] ?? match[1] ?? \"\").trim();\n if (!p || seen.has(p)) continue;\n seen.add(p);\n out.push(p);\n if (out.length >= 10) break;\n }\n return out;\n };\n\n try {\n const operations = parseApplyPatch(patchString);\n parsedOps = operations;\n\n for (const op of operations) {\n const opPath = normalizeFsPathForPolicy(op.filePath);\n if (!isAllowedRouteFilePath(opPath)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: only route files named \"page.tsx\" or \"page.config.ts\" may be modified.\\n` +\n `Found operation on: \"${opPath}\"`,\n allowed: Array.from([\"page.tsx\", \"page.config.ts\"]),\n };\n }\n\n if (op.kind === \"update\" && op.moveTo && op.moveTo !== op.filePath) {\n const moveToPath = normalizeFsPathForPolicy(op.moveTo);\n if (!isAllowedRouteFilePath(moveToPath)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: move target must be a route file named \"page.tsx\" or \"page.config.ts\".\\n` +\n `From: \"${opPath}\"\\n` +\n `To: \"${moveToPath}\"`,\n allowed: Array.from([\"page.tsx\", \"page.config.ts\"]),\n };\n }\n\n const fromName = opPath.split(\"/\").pop() ?? \"\";\n const toName = moveToPath.split(\"/\").pop() ?? \"\";\n if (fromName !== toName) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: renaming between route file types is not allowed.\\n` +\n `From: \"${opPath}\"\\n` +\n `To: \"${moveToPath}\"`,\n };\n }\n }\n\n if (isPageTsxPath(opPath)) {\n if (op.kind === \"update\") {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: updates to \"page.tsx\" are not allowed for any route. ` +\n `Only Add File (create) or Delete File is allowed.\\n` +\n `Path: \"${opPath}\"`,\n rule: \"page.tsx is immutable after creation\",\n };\n }\n\n if (op.kind === \"add\") {\n const { content: after } = applyHunksToContent(\"\", op.hunks);\n if (!matchesPageTsxTemplate(after)) {\n return {\n success: false,\n rejected: true,\n error:\n `apply_patch rejected: new \"page.tsx\" must match the exact required template (byte-for-byte).\\n` +\n `Path: \"${opPath}\"\\n` +\n `Expected:\\n${PAGE_TSX_TEMPLATE}`,\n rule: \"page.tsx must match template on creation\",\n };\n }\n }\n }\n }\n\n let changed = false;\n const warnings: string[] = [];\n\n for (const op of operations) {\n if (!isTextFilePath(op.filePath)) {\n throw new Error(`Binary or unsupported file type in patch: \"${op.filePath}\"`);\n }\n if (op.kind === \"update\" && op.moveTo && !isTextFilePath(op.moveTo)) {\n throw new Error(`Binary or unsupported file type in patch: \"${op.moveTo}\"`);\n }\n\n const fullPath = toWorkspacePath(workspaceRoot, op.filePath);\n\n if (op.kind === \"delete\") {\n console.log(\"Tool apply_patch (delete)\", { path: fullPath });\n try {\n await fs.rmFile(fullPath);\n changed = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Delete File failed for \"${op.filePath}\": ${message}`);\n }\n continue;\n }\n\n if (op.kind === \"add\") {\n console.log(\"Tool apply_patch (add)\", { path: fullPath });\n try {\n const { content: after, changed: opChanged } = applyHunksToContent(\n \"\",\n op.hunks,\n );\n await fs.mkdirp(path.dirname(fullPath));\n await fs.writeFile(fullPath, after);\n if (!opChanged) warnings.push(`Add File produced no changes for \"${op.filePath}\".`);\n changed = changed || opChanged;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Add File failed for \"${op.filePath}\": ${message}`);\n }\n continue;\n }\n\n if (op.kind === \"update\") {\n console.log(\"Tool apply_patch (update)\", { path: fullPath });\n try {\n try {\n await fs.stat(fullPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n throw new Error(`\"${op.filePath}\" not found.`);\n }\n throw err;\n }\n\n const before = await fs.readFile(fullPath);\n await addDebugSnapshot(op.filePath, `BEFORE (${op.filePath}):`);\n\n const { content: after, changed: contentChanged } = applyHunksToContent(\n before,\n op.hunks,\n );\n\n if (op.moveTo && op.moveTo !== op.filePath) {\n const moveToPath = toWorkspacePath(workspaceRoot, op.moveTo);\n console.log(\"Tool apply_patch (move)\", {\n from: fullPath,\n to: moveToPath,\n });\n await fs.mkdirp(path.dirname(moveToPath));\n await fs.writeFile(moveToPath, after);\n await fs.rmFile(fullPath);\n changed = true;\n continue;\n }\n\n if (!contentChanged) {\n warnings.push(`Update File made no changes for \"${op.filePath}\".`);\n continue;\n }\n\n await fs.mkdirp(path.dirname(fullPath));\n await fs.writeFile(fullPath, after);\n changed = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Update File failed for \"${op.filePath}\": ${message}`);\n }\n }\n }\n\n return { success: true, changed, warnings: warnings.length > 0 ? warnings : undefined };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\"Tool apply_patch failed\", err, { message });\n\n try {\n if (debugFiles.length < 3) {\n const paths = parsedOps\n ? parsedOps.flatMap((op) =>\n op.kind === \"update\" && op.moveTo\n ? [op.filePath, op.moveTo]\n : [op.filePath],\n )\n : extractPatchPaths(patchString);\n\n for (const p of paths) {\n if (debugFiles.length >= 3) break;\n await addDebugSnapshot(p);\n }\n\n if (debugFiles.length < 3 && parsedOps) {\n for (const op of parsedOps) {\n if (debugFiles.length >= 3) break;\n if (op.kind === \"add\") debugFiles.push({ path: op.filePath, head: \"(new file)\" });\n if (op.kind === \"delete\") debugFiles.push({ path: op.filePath, head: \"(deleted)\" });\n }\n }\n }\n } catch {\n // best-effort only\n }\n\n return {\n success: false,\n error: message,\n debug: debugFiles.length > 0 ? { files: debugFiles.slice(0, 3) } : undefined,\n };\n }\n };\n};\n"]}
@@ -49,7 +49,7 @@ export const createCreateNewRouteImpl = (deps) => {
49
49
  const appDir = toWorkspacePath(workspaceRoot, "app");
50
50
  const ensureRouteExists = async (segments) => {
51
51
  const parentDir = path.join(appDir, ...segments.slice(0, -1));
52
- const seg = segments[segments.length - 1];
52
+ const seg = segments.slice(-1)[0];
53
53
  const finalDir = path.join(parentDir, seg);
54
54
  try {
55
55
  const st = await coreFs.stat(finalDir);
@@ -1 +1 @@
1
- {"version":3,"file":"createNewRoute.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractAllIds } from \"../helpers/elementid.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isSafeSegment,\n normalizeRouteSegments,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype CreateNewRouteResult =\n | {\n success: true;\n route: string;\n created_files: string[];\n page_config_json: unknown;\n }\n | { success: false; error: string };\n\nconst PAGE_TSX_TEMPLATE = [\n 'import { RenderElement } from \"@/lib/renderer/RenderElement\";',\n 'import pageConfig from \"./pageConfig.json\";',\n 'import type { BuilderElement } from \"@/types/elements\";',\n \"\",\n \"export default function Page() {\",\n \" const config = pageConfig as { elements: BuilderElement[] };\",\n \" return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\",\n \"}\",\n \"\",\n].join(\"\\n\");\n\nconst DEFAULT_PAGE_CONFIG = (() => {\n const elements: any[] = [\n {\n id: \"root\",\n type: \"div\",\n className: \"min-h-screen p-6 bg-background text-foreground\",\n props: {},\n },\n ];\n\n // Validate uniqueness (and keep deterministic IDs).\n const ids = extractAllIds(elements as any);\n if (!ids.has(\"root\")) {\n throw new Error(\"DEFAULT_PAGE_CONFIG ids must be stable and unique\");\n }\n\n return JSON.stringify({ elements }, null, 2) + \"\\n\";\n})();\n\nexport const createCreateNewRouteImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs: coreFs } = deps;\n\n return async (parentRoute: string, routeName: string) => {\n let parentSegments = normalizeRouteSegments(parentRoute);\n const routeSegment = String(routeName ?? \"\").trim();\n\n if (!isSafeSegment(routeSegment)) {\n return {\n success: false,\n error: \"Invalid route name\",\n } satisfies CreateNewRouteResult;\n }\n // Check if the parentRoute is proper (all segments are safe).\n // If not proper, create the new route under the '/' route.\n if (parentSegments.some((s) => !isSafeSegment(s))) {\n parentSegments = [];\n }\n\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n\n const ensureRouteExists = async (segments: string[]) => {\n const parentDir = path.join(appDir, ...segments.slice(0, -1));\n const seg = segments[segments.length - 1];\n const finalDir = path.join(parentDir, seg);\n\n try {\n const st = await coreFs.stat(finalDir);\n if (st.isDirectory()) {\n return;\n }\n } catch {}\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${seg}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n await coreFs.mkdirp(tmpDir);\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n await fs.rename(tmpDir, finalDir);\n };\n\n try {\n for (let i = 1; i <= parentSegments.length; i++) {\n await ensureRouteExists(parentSegments.slice(0, i));\n }\n } catch (err) {\n return {\n success: false,\n error: `Failed to ensure parent route: ${err instanceof Error ? err.message : String(err)}`,\n } satisfies CreateNewRouteResult;\n }\n\n const parentDir = path.join(appDir, ...parentSegments);\n const finalDir = path.join(parentDir, routeSegment);\n\n // Route must not already exist.\n try {\n await coreFs.stat(finalDir);\n return {\n success: false,\n error: \"Route already exists\",\n } satisfies CreateNewRouteResult;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code && code !== \"ENOENT\") {\n return {\n success: false,\n error: \"Route check failed\",\n } satisfies CreateNewRouteResult;\n }\n }\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${routeSegment}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n const rollback = async () => {\n // Rollback any partially-created temp output.\n try {\n await fs.rm(tmpDir, { recursive: true, force: true });\n } catch {\n // best-effort cleanup only\n }\n };\n\n try {\n await coreFs.mkdirp(tmpDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Temp folder create failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write page.tsx failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write pageConfig failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n // Commit: move temp dir into place (best-effort atomic within same parent).\n await fs.rename(tmpDir, finalDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Finalize route failed\",\n } satisfies CreateNewRouteResult;\n }\n\n const routePath =\n \"/\" + [...parentSegments, routeSegment].filter(Boolean).join(\"/\");\n\n let pageConfigJson: unknown = null;\n try {\n pageConfigJson = JSON.parse(DEFAULT_PAGE_CONFIG);\n } catch {\n // shouldn't happen, but keep the tool robust\n pageConfigJson = { elements: [] };\n }\n\n return {\n success: true,\n route: routePath,\n created_files: [\n path\n .join(\"app\", ...parentSegments, routeSegment, \"page.tsx\")\n .replace(/\\\\/g, \"/\"),\n path\n .join(\"app\", ...parentSegments, routeSegment, \"pageConfig.json\")\n .replace(/\\\\/g, \"/\"),\n ],\n page_config_json: pageConfigJson,\n } satisfies CreateNewRouteResult;\n };\n};\n\nexport const DEFAULT_PAGE_CONFIG_JSON = DEFAULT_PAGE_CONFIG;\nexport const PAGE_TSX_TEMPLATE_STRING = PAGE_TSX_TEMPLATE;\n"]}
1
+ {"version":3,"file":"createNewRoute.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,aAAa,EACb,sBAAsB,GACvB,MAAM,sCAAsC,CAAC;AAY9C,MAAM,iBAAiB,GAAG;IACxB,+DAA+D;IAC/D,6CAA6C;IAC7C,yDAAyD;IACzD,EAAE;IACF,kCAAkC;IAClC,gEAAgE;IAChE,8EAA8E;IAC9E,GAAG;IACH,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE;IAChC,MAAM,QAAQ,GAAU;QACtB;YACE,EAAE,EAAE,MAAM;YACV,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,gDAAgD;YAC3D,KAAK,EAAE,EAAE;SACV;KACF,CAAC;IAEF,oDAAoD;IACpD,MAAM,GAAG,GAAG,aAAa,CAAC,QAAe,CAAC,CAAC;IAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AACtD,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,IAAmB,EAAE,EAAE;IAC9D,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE3C,OAAO,KAAK,EAAE,WAAmB,EAAE,SAAiB,EAAE,EAAE;QACtD,IAAI,cAAc,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEpD,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,oBAAoB;aACG,CAAC;QACnC,CAAC;QACD,8DAA8D;QAC9D,2DAA2D;QAC3D,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,cAAc,GAAG,EAAE,CAAC;QACtB,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QAErD,MAAM,iBAAiB,GAAG,KAAK,EAAE,QAAkB,EAAE,EAAE;YACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAE3C,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;oBACrB,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAEV,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,SAAS,EACT,sBAAsB,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CACjF,CAAC;YAEF,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5B,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC;YACzE,MAAM,MAAM,CAAC,SAAS,CACpB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACpC,mBAAmB,CACpB,CAAC;YACF,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChD,MAAM,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aAC7D,CAAC;QACnC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAEpD,gCAAgC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,sBAAsB;aACC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,oBAAoB;iBACG,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,SAAS,EACT,sBAAsB,YAAY,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAC1F,CAAC;QAEF,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,2BAA2B;aACJ,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,uBAAuB;aACA,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CACpB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACpC,mBAAmB,CACpB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,yBAAyB;aACF,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,4EAA4E;YAC5E,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,uBAAuB;aACA,CAAC;QACnC,CAAC;QAED,MAAM,SAAS,GACb,GAAG,GAAG,CAAC,GAAG,cAAc,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,IAAI,cAAc,GAAY,IAAI,CAAC;QACnC,IAAI,CAAC;YACH,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;YAC7C,cAAc,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,aAAa,EAAE;gBACb,IAAI;qBACD,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,EAAE,YAAY,EAAE,UAAU,CAAC;qBACxD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;gBACtB,IAAI;qBACD,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,EAAE,YAAY,EAAE,iBAAiB,CAAC;qBAC/D,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACvB;YACD,gBAAgB,EAAE,cAAc;SACF,CAAC;IACnC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,iBAAiB,CAAC","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractAllIds } from \"../helpers/elementid.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isSafeSegment,\n normalizeRouteSegments,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype CreateNewRouteResult =\n | {\n success: true;\n route: string;\n created_files: string[];\n page_config_json: unknown;\n }\n | { success: false; error: string };\n\nconst PAGE_TSX_TEMPLATE = [\n 'import { RenderElement } from \"@/lib/renderer/RenderElement\";',\n 'import pageConfig from \"./pageConfig.json\";',\n 'import type { BuilderElement } from \"@/types/elements\";',\n \"\",\n \"export default function Page() {\",\n \" const config = pageConfig as { elements: BuilderElement[] };\",\n \" return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\",\n \"}\",\n \"\",\n].join(\"\\n\");\n\nconst DEFAULT_PAGE_CONFIG = (() => {\n const elements: any[] = [\n {\n id: \"root\",\n type: \"div\",\n className: \"min-h-screen p-6 bg-background text-foreground\",\n props: {},\n },\n ];\n\n // Validate uniqueness (and keep deterministic IDs).\n const ids = extractAllIds(elements as any);\n if (!ids.has(\"root\")) {\n throw new Error(\"DEFAULT_PAGE_CONFIG ids must be stable and unique\");\n }\n\n return JSON.stringify({ elements }, null, 2) + \"\\n\";\n})();\n\nexport const createCreateNewRouteImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs: coreFs } = deps;\n\n return async (parentRoute: string, routeName: string) => {\n let parentSegments = normalizeRouteSegments(parentRoute);\n const routeSegment = String(routeName ?? \"\").trim();\n\n if (!isSafeSegment(routeSegment)) {\n return {\n success: false,\n error: \"Invalid route name\",\n } satisfies CreateNewRouteResult;\n }\n // Check if the parentRoute is proper (all segments are safe).\n // If not proper, create the new route under the '/' route.\n if (parentSegments.some((s) => !isSafeSegment(s))) {\n parentSegments = [];\n }\n\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n\n const ensureRouteExists = async (segments: string[]) => {\n const parentDir = path.join(appDir, ...segments.slice(0, -1));\n const seg = segments.slice(-1)[0];\n const finalDir = path.join(parentDir, seg);\n\n try {\n const st = await coreFs.stat(finalDir);\n if (st.isDirectory()) {\n return;\n }\n } catch {}\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${seg}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n await coreFs.mkdirp(tmpDir);\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n await fs.rename(tmpDir, finalDir);\n };\n\n try {\n for (let i = 1; i <= parentSegments.length; i++) {\n await ensureRouteExists(parentSegments.slice(0, i));\n }\n } catch (err) {\n return {\n success: false,\n error: `Failed to ensure parent route: ${err instanceof Error ? err.message : String(err)}`,\n } satisfies CreateNewRouteResult;\n }\n\n const parentDir = path.join(appDir, ...parentSegments);\n const finalDir = path.join(parentDir, routeSegment);\n\n // Route must not already exist.\n try {\n await coreFs.stat(finalDir);\n return {\n success: false,\n error: \"Route already exists\",\n } satisfies CreateNewRouteResult;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code && code !== \"ENOENT\") {\n return {\n success: false,\n error: \"Route check failed\",\n } satisfies CreateNewRouteResult;\n }\n }\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${routeSegment}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n const rollback = async () => {\n // Rollback any partially-created temp output.\n try {\n await fs.rm(tmpDir, { recursive: true, force: true });\n } catch {\n // best-effort cleanup only\n }\n };\n\n try {\n await coreFs.mkdirp(tmpDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Temp folder create failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write page.tsx failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write pageConfig failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n // Commit: move temp dir into place (best-effort atomic within same parent).\n await fs.rename(tmpDir, finalDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Finalize route failed\",\n } satisfies CreateNewRouteResult;\n }\n\n const routePath =\n \"/\" + [...parentSegments, routeSegment].filter(Boolean).join(\"/\");\n\n let pageConfigJson: unknown = null;\n try {\n pageConfigJson = JSON.parse(DEFAULT_PAGE_CONFIG);\n } catch {\n // shouldn't happen, but keep the tool robust\n pageConfigJson = { elements: [] };\n }\n\n return {\n success: true,\n route: routePath,\n created_files: [\n path\n .join(\"app\", ...parentSegments, routeSegment, \"page.tsx\")\n .replace(/\\\\/g, \"/\"),\n path\n .join(\"app\", ...parentSegments, routeSegment, \"pageConfig.json\")\n .replace(/\\\\/g, \"/\"),\n ],\n page_config_json: pageConfigJson,\n } satisfies CreateNewRouteResult;\n };\n};\n\nexport const DEFAULT_PAGE_CONFIG_JSON = DEFAULT_PAGE_CONFIG;\nexport const PAGE_TSX_TEMPLATE_STRING = PAGE_TSX_TEMPLATE;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"deleteElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/deleteElement.impl.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAG3C,OAAO,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;;;;EAuD/C,CAAC"}
1
+ {"version":3,"file":"deleteElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/deleteElement.impl.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAG3C,OAAO,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;;;;EAwB/C,CAAC"}
@@ -1,46 +1,14 @@
1
- import { deleteElementById, ensureElementIds, extractAllIdsDeep, resolvePageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
1
+ import { deleteElementById, loadAndPreparePageConfig, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
2
2
  export const createDeleteElementImpl = (deps) => {
3
3
  const { workspaceRoot, fs } = deps;
4
4
  return async (route, elementId) => {
5
5
  const id = String(elementId ?? "").trim();
6
6
  if (!id)
7
7
  return { success: false, error: "invalid element_id" };
8
- let configPath;
9
- try {
10
- configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);
11
- }
12
- catch (err) {
13
- return {
14
- success: false,
15
- error: err instanceof Error ? err.message : String(err),
16
- };
17
- }
18
- let before = "";
19
- try {
20
- before = await fs.readFile(configPath);
21
- }
22
- catch (err) {
23
- const code = err?.code;
24
- if (code === "ENOENT")
25
- return { success: false, error: "not found" };
26
- return {
27
- success: false,
28
- error: err instanceof Error ? err.message : String(err),
29
- };
30
- }
31
- let parsed;
32
- try {
33
- parsed = parsePageConfigJson(before);
34
- }
35
- catch (err) {
36
- return {
37
- success: false,
38
- error: err instanceof Error ? err.message : String(err),
39
- };
40
- }
41
- const elements = parsed.elements ?? [];
42
- const existingIds = extractAllIdsDeep(elements);
43
- ensureElementIds(elements, existingIds);
8
+ const prep = await loadAndPreparePageConfig(workspaceRoot, route, fs);
9
+ if (!prep.success)
10
+ return prep;
11
+ const { configPath, elements } = prep;
44
12
  const deleted = deleteElementById(elements, id);
45
13
  if (!deleted)
46
14
  return { success: true, changed: false };
@@ -1 +1 @@
1
- {"version":3,"file":"deleteElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/deleteElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n deleteElementById,\n ensureElementIds,\n extractAllIdsDeep,\n resolvePageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createDeleteElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, elementId: string) => {\n const id = String(elementId ?? \"\").trim();\n if (!id) return { success: false, error: \"invalid element_id\" };\n\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n const deleted = deleteElementById(elements, id);\n if (!deleted) return { success: true, changed: false };\n\n const after = stringifyPageConfigJson({ elements });\n\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, deleted_id: id };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"deleteElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/deleteElement.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,sCAAsC,CAAC;AAG9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,IAAmB,EAAE,EAAE;IAC7D,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEnC,OAAO,KAAK,EAAE,KAAa,EAAE,SAAiB,EAAE,EAAE;QAChD,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;QAEhE,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAEtC,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAEvD,MAAM,KAAK,GAAG,uBAAuB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n deleteElementById,\n loadAndPreparePageConfig,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createDeleteElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, elementId: string) => {\n const id = String(elementId ?? \"\").trim();\n if (!id) return { success: false, error: \"invalid element_id\" };\n\n const prep = await loadAndPreparePageConfig(workspaceRoot, route, fs);\n if (!prep.success) return prep;\n\n const { configPath, elements } = prep;\n\n const deleted = deleteElementById(elements, id);\n if (!deleted) return { success: true, changed: false };\n\n const after = stringifyPageConfigJson({ elements });\n\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, deleted_id: id };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAyCxD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAIvD,aAAa,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,WAAW,MAAM,EACjB,gBAAgB,GAAG,EAAE,EACrB,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHpB,CAAC"}
1
+ {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAyCxD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAIvD,aAAa,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,WAAW,MAAM,EACjB,gBAAgB,GAAG,EAAE,EACrB,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8EpB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { resolveUnsplashImagesDeep } from "../../../image/unsplash.service.js";
2
- import { ensureElementIds, extractAllIdsDeep, findElementById, resolvePageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
2
+ import { ensureElementIds, findElementById, loadAndPreparePageConfig, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
3
3
  import { InsertElementArgsZod } from "../validators/builderElement.zod.js";
4
4
  function reconstructTree(flatElements) {
5
5
  const rootFlats = flatElements.filter((el) => el.parentId === "parent");
@@ -12,7 +12,7 @@ function reconstructTree(flatElements) {
12
12
  type: flat.type,
13
13
  className: flat.className,
14
14
  visible: flat.visible,
15
- props: flat.props ? JSON.parse(JSON.stringify(flat.props)) : undefined,
15
+ props: flat.props ? structuredClone(flat.props) : undefined,
16
16
  children: [],
17
17
  });
18
18
  }
@@ -57,42 +57,10 @@ export const createInsertElementImpl = (deps) => {
57
57
  if (!parent_id)
58
58
  return { success: false, error: "invalid parent_id" };
59
59
  const before_id = String(parsedArgs.data.before_id ?? "").trim();
60
- let configPath;
61
- try {
62
- configPath = await resolvePageConfigJsonPath(workspaceRoot, parsedArgs.data.route, fs);
63
- }
64
- catch (err) {
65
- return {
66
- success: false,
67
- error: err instanceof Error ? err.message : String(err),
68
- };
69
- }
70
- let before = "";
71
- try {
72
- before = await fs.readFile(configPath);
73
- }
74
- catch (err) {
75
- const code = err?.code;
76
- if (code === "ENOENT")
77
- return { success: false, error: "not found" };
78
- return {
79
- success: false,
80
- error: err instanceof Error ? err.message : String(err),
81
- };
82
- }
83
- let parsed;
84
- try {
85
- parsed = parsePageConfigJson(before);
86
- }
87
- catch (err) {
88
- return {
89
- success: false,
90
- error: err instanceof Error ? err.message : String(err),
91
- };
92
- }
93
- const elements = parsed.elements ?? [];
94
- const existingIds = extractAllIdsDeep(elements);
95
- ensureElementIds(elements, existingIds);
60
+ const prep = await loadAndPreparePageConfig(workspaceRoot, parsedArgs.data.route, fs);
61
+ if (!prep.success)
62
+ return prep;
63
+ const { configPath, elements, existingIds } = prep;
96
64
  // Clone + inject ids for the inserted element subtree.
97
65
  let toInsert;
98
66
  try {
@@ -115,14 +83,9 @@ export const createInsertElementImpl = (deps) => {
115
83
  if (!anyParent.children || !Array.isArray(anyParent.children))
116
84
  anyParent.children = [];
117
85
  const children = anyParent.children;
118
- if (before_id) {
119
- const idx = children.findIndex((c) => String(c?.id ?? "") === before_id);
120
- if (idx >= 0) {
121
- children.splice(idx, 0, ...toInsert);
122
- }
123
- else {
124
- children.push(...toInsert);
125
- }
86
+ const idx = before_id ? children.findIndex((c) => String(c?.id ?? "") === before_id) : -1;
87
+ if (idx >= 0) {
88
+ children.splice(idx, 0, ...toInsert);
126
89
  }
127
90
  else {
128
91
  children.push(...toInsert);
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n resolvePageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nfunction reconstructTree(flatElements: any[]): BuilderElement[] {\n const rootFlats = flatElements.filter((el) => el.parentId === \"parent\");\n if (rootFlats.length === 0) {\n throw new Error(\"No root element found with parentId 'parent'\");\n }\n\n const buildMap = new Map<string, any>();\n for (const flat of flatElements) {\n buildMap.set(flat.id, {\n type: flat.type,\n className: flat.className,\n visible: flat.visible,\n props: flat.props ? JSON.parse(JSON.stringify(flat.props)) : undefined,\n children: [],\n });\n }\n\n for (const flat of flatElements) {\n if (flat.parentId === \"parent\") {\n continue;\n }\n const parentNode = buildMap.get(flat.parentId);\n if (!parentNode) {\n throw new Error(\n `Parent element with id '${flat.parentId}' not found in the list`,\n );\n }\n const currentNode = buildMap.get(flat.id);\n if (currentNode) {\n if (!parentNode.children) {\n parentNode.children = [];\n }\n parentNode.children.push(currentNode);\n }\n }\n\n return rootFlats.map((rootFlat) => buildMap.get(rootFlat.id));\n}\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n inputElements?: any[],\n beforeId?: string,\n ) => {\n const rawArgs =\n typeof routeOrArgs === \"object\" && routeOrArgs !== null\n ? (routeOrArgs as Record<string, unknown>)\n : {\n route: routeOrArgs,\n parent_id: parentId,\n before_id: beforeId,\n elements: inputElements,\n };\n\n const parsedArgs = InsertElementArgsZod.safeParse(rawArgs);\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parsedArgs.data.parent_id ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n const before_id = String(parsedArgs.data.before_id ?? \"\").trim();\n\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, parsedArgs.data.route, fs);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n let toInsert: BuilderElement[];\n try {\n toInsert = reconstructTree(parsedArgs.data.elements);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n for (const el of toInsert) {\n await resolveUnsplashImagesDeep(el);\n }\n ensureElementIds(toInsert, existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\n const children = anyParent.children as BuilderElement[];\n if (before_id) {\n const idx = children.findIndex((c: any) => String(c?.id ?? \"\") === before_id);\n if (idx >= 0) {\n children.splice(idx, 0, ...toInsert);\n } else {\n children.push(...toInsert);\n }\n } else {\n children.push(...toInsert);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert[0] as any).id,\n inserted_ids: toInsert.map((el: any) => el.id),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport {\n ensureElementIds,\n findElementById,\n loadAndPreparePageConfig,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nfunction reconstructTree(flatElements: any[]): BuilderElement[] {\n const rootFlats = flatElements.filter((el) => el.parentId === \"parent\");\n if (rootFlats.length === 0) {\n throw new Error(\"No root element found with parentId 'parent'\");\n }\n\n const buildMap = new Map<string, any>();\n for (const flat of flatElements) {\n buildMap.set(flat.id, {\n type: flat.type,\n className: flat.className,\n visible: flat.visible,\n props: flat.props ? structuredClone(flat.props) : undefined,\n children: [],\n });\n }\n\n for (const flat of flatElements) {\n if (flat.parentId === \"parent\") {\n continue;\n }\n const parentNode = buildMap.get(flat.parentId);\n if (!parentNode) {\n throw new Error(\n `Parent element with id '${flat.parentId}' not found in the list`,\n );\n }\n const currentNode = buildMap.get(flat.id);\n if (currentNode) {\n if (!parentNode.children) {\n parentNode.children = [];\n }\n parentNode.children.push(currentNode);\n }\n }\n\n return rootFlats.map((rootFlat) => buildMap.get(rootFlat.id));\n}\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n inputElements?: any[],\n beforeId?: string,\n ) => {\n const rawArgs =\n typeof routeOrArgs === \"object\" && routeOrArgs !== null\n ? (routeOrArgs as Record<string, unknown>)\n : {\n route: routeOrArgs,\n parent_id: parentId,\n before_id: beforeId,\n elements: inputElements,\n };\n\n const parsedArgs = InsertElementArgsZod.safeParse(rawArgs);\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parsedArgs.data.parent_id ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n const before_id = String(parsedArgs.data.before_id ?? \"\").trim();\n\n const prep = await loadAndPreparePageConfig(workspaceRoot, parsedArgs.data.route, fs);\n if (!prep.success) return prep;\n\n const { configPath, elements, existingIds } = prep;\n\n // Clone + inject ids for the inserted element subtree.\n let toInsert: BuilderElement[];\n try {\n toInsert = reconstructTree(parsedArgs.data.elements);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n for (const el of toInsert) {\n await resolveUnsplashImagesDeep(el);\n }\n ensureElementIds(toInsert, existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\n const children = anyParent.children as BuilderElement[];\n const idx = before_id ? children.findIndex((c: any) => String(c?.id ?? \"\") === before_id) : -1;\n if (idx >= 0) {\n children.splice(idx, 0, ...toInsert);\n } else {\n children.push(...toInsert);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert[0] as any).id,\n inserted_ids: toInsert.map((el: any) => el.id),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"updateClassName.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateClassName.impl.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,yBAAyB,GAAI,MAAM,aAAa,MAG7C,OAAO,MAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;EAwDlE,CAAC"}
1
+ {"version":3,"file":"updateClassName.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateClassName.impl.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,yBAAyB,GAAI,MAAM,aAAa,MAG7C,OAAO,MAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;EAyBlE,CAAC"}