@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":"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 const 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 if (parentSegments.some((s) => !isSafeSegment(s))) {\n return {\n success: false,\n error: \"Invalid parent route\",\n } satisfies CreateNewRouteResult;\n }\n\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n const parentDir = path.join(appDir, ...parentSegments);\n const finalDir = path.join(parentDir, routeSegment);\n\n // Parent must exist (don't implicitly create arbitrary routes).\n try {\n const st = await coreFs.stat(parentDir);\n if (!st.isDirectory()) {\n return {\n success: false,\n error: \"Parent not a folder\",\n } satisfies CreateNewRouteResult;\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n return {\n success: false,\n error: \"Parent route missing\",\n } satisfies CreateNewRouteResult;\n }\n return {\n success: false,\n error: \"Parent check failed\",\n } satisfies CreateNewRouteResult;\n }\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":"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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,4 +1,4 @@
1
- import { deleteElementById, ensureElementIds, extractAllIdsDeep, getPageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
1
+ import { deleteElementById, ensureElementIds, extractAllIdsDeep, resolvePageConfigJsonPath, parsePageConfigJson, 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) => {
@@ -7,7 +7,7 @@ export const createDeleteElementImpl = (deps) => {
7
7
  return { success: false, error: "invalid element_id" };
8
8
  let configPath;
9
9
  try {
10
- configPath = getPageConfigJsonPath(workspaceRoot, route);
10
+ configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);
11
11
  }
12
12
  catch (err) {
13
13
  return {
@@ -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 getPageConfigJsonPath,\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 = getPageConfigJsonPath(workspaceRoot, route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n 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":"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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,5 +1,5 @@
1
1
  import { resolveUnsplashImagesDeep } from "../../../image/unsplash.service.js";
2
- import { ensureElementIds, extractAllIdsDeep, findElementById, getPageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
2
+ import { ensureElementIds, extractAllIdsDeep, findElementById, resolvePageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
3
3
  import { InsertElementArgsZod } from "../validators/builderElement.zod.js";
4
4
  export const createInsertElementImpl = (deps) => {
5
5
  const { workspaceRoot, fs } = deps;
@@ -26,7 +26,7 @@ export const createInsertElementImpl = (deps) => {
26
26
  const before_id = String(parsedArgs.data.before_id ?? "").trim();
27
27
  let configPath;
28
28
  try {
29
- configPath = getPageConfigJsonPath(workspaceRoot, parsedArgs.data.route);
29
+ configPath = await resolvePageConfigJsonPath(workspaceRoot, parsedArgs.data.route, fs);
30
30
  }
31
31
  catch (err) {
32
32
  return {
@@ -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 getPageConfigJsonPath,\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\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n element?: BuilderElement,\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 element,\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 = getPageConfigJsonPath(workspaceRoot, parsedArgs.data.route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n const toInsert = JSON.parse(\n JSON.stringify(parsedArgs.data.element ?? null),\n ) as BuilderElement;\n await resolveUnsplashImagesDeep(toInsert);\n ensureElementIds([toInsert], existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\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 as any).id,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport {\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\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n element?: BuilderElement,\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 element,\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 const toInsert = JSON.parse(\n JSON.stringify(parsedArgs.data.element ?? null),\n ) as BuilderElement;\n await resolveUnsplashImagesDeep(toInsert);\n ensureElementIds([toInsert], existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\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 as any).id,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { ensureElementIds, extractAllIdsDeep, findElementById, getPageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
1
+ import { ensureElementIds, extractAllIdsDeep, findElementById, resolvePageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
2
2
  export const createUpdateClassNameImpl = (deps) => {
3
3
  const { workspaceRoot, fs } = deps;
4
4
  return async (route, elementId, className) => {
@@ -7,7 +7,7 @@ export const createUpdateClassNameImpl = (deps) => {
7
7
  return { success: false, error: "invalid element_id" };
8
8
  let configPath;
9
9
  try {
10
- configPath = getPageConfigJsonPath(workspaceRoot, route);
10
+ configPath = await resolvePageConfigJsonPath(workspaceRoot, route, fs);
11
11
  }
12
12
  catch (err) {
13
13
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"updateClassName.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateClassName.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n getPageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createUpdateClassNameImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, elementId: string, className: 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 = getPageConfigJsonPath(workspaceRoot, route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n const el = findElementById(elements, id);\n if (!el) return { success: false, error: \"element not found\" };\n\n (el as any).className = String(className ?? \"\");\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, updated_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":"updateClassName.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateClassName.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n resolvePageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createUpdateClassNameImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (route: string, elementId: string, className: 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 el = findElementById(elements, id);\n if (!el) return { success: false, error: \"element not found\" };\n\n (el as any).className = String(className ?? \"\");\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, updated_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,5 +1,5 @@
1
1
  import { resolveUnsplashImageForElement } from "../../../image/unsplash.service.js";
2
- import { ensureElementIds, extractAllIdsDeep, findElementById, getPageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
2
+ import { ensureElementIds, extractAllIdsDeep, findElementById, resolvePageConfigJsonPath, parsePageConfigJson, stringifyPageConfigJson, writeFileAtomic, } from "../helpers/pageConfigJson.helpers.js";
3
3
  const applyPropsPatch = (el, patch) => {
4
4
  const anyEl = el;
5
5
  if (!anyEl.props || typeof anyEl.props !== "object")
@@ -31,7 +31,7 @@ export const createUpdatePropsImpl = (deps) => {
31
31
  return { success: false, error: "invalid element_id" };
32
32
  let configPath;
33
33
  try {
34
- configPath = getPageConfigJsonPath(workspaceRoot, args.route);
34
+ configPath = await resolvePageConfigJsonPath(workspaceRoot, args.route, fs);
35
35
  }
36
36
  catch (err) {
37
37
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"updateProps.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateProps.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImageForElement } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement, OnClickAction } from \"../../../types/elements.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n getPageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype UpdatePropsArgs = {\n route: string;\n element_id: string;\n} & Partial<{\n onClick: OnClickAction;\n text: string;\n href: string;\n placeholder: string;\n alt: string;\n target: string;\n rel: string;\n value: string;\n type: string;\n name: string;\n size: number;\n color: string;\n strokeWidth: number;\n}>;\n\nconst applyPropsPatch = (el: BuilderElement, patch: UpdatePropsArgs) => {\n const anyEl = el as any;\n if (!anyEl.props || typeof anyEl.props !== \"object\") anyEl.props = {};\n\n const apply = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n anyEl.props[key] = value;\n };\n\n apply(\"onClick\", patch.onClick);\n apply(\"text\", patch.text);\n apply(\"href\", patch.href);\n apply(\"placeholder\", patch.placeholder);\n apply(\"alt\", patch.alt);\n apply(\"target\", patch.target);\n apply(\"rel\", patch.rel);\n apply(\"value\", patch.value);\n apply(\"type\", patch.type);\n\n apply(\"name\", patch.name);\n apply(\"size\", patch.size);\n apply(\"color\", patch.color);\n apply(\"strokeWidth\", patch.strokeWidth);\n};\n\nexport const createUpdatePropsImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (args: UpdatePropsArgs) => {\n const id = String(args?.element_id ?? \"\").trim();\n if (!id) return { success: false, error: \"invalid element_id\" };\n\n let configPath: string;\n try {\n configPath = getPageConfigJsonPath(workspaceRoot, args.route);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n const el = findElementById(elements, id);\n if (!el) return { success: false, error: \"element not found\" };\n\n applyPropsPatch(el, args);\n\n if (el.type === \"image\") {\n const anyEl = el as any;\n const alt = String(args.alt ?? anyEl?.props?.alt ?? \"\").trim();\n await resolveUnsplashImageForElement(el, alt);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, updated_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":"updateProps.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateProps.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImageForElement } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement, OnClickAction } 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 { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype UpdatePropsArgs = {\n route: string;\n element_id: string;\n} & Partial<{\n onClick: OnClickAction;\n text: string;\n href: string;\n placeholder: string;\n alt: string;\n target: string;\n rel: string;\n value: string;\n type: string;\n name: string;\n size: number;\n color: string;\n strokeWidth: number;\n}>;\n\nconst applyPropsPatch = (el: BuilderElement, patch: UpdatePropsArgs) => {\n const anyEl = el as any;\n if (!anyEl.props || typeof anyEl.props !== \"object\") anyEl.props = {};\n\n const apply = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n anyEl.props[key] = value;\n };\n\n apply(\"onClick\", patch.onClick);\n apply(\"text\", patch.text);\n apply(\"href\", patch.href);\n apply(\"placeholder\", patch.placeholder);\n apply(\"alt\", patch.alt);\n apply(\"target\", patch.target);\n apply(\"rel\", patch.rel);\n apply(\"value\", patch.value);\n apply(\"type\", patch.type);\n\n apply(\"name\", patch.name);\n apply(\"size\", patch.size);\n apply(\"color\", patch.color);\n apply(\"strokeWidth\", patch.strokeWidth);\n};\n\nexport const createUpdatePropsImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (args: UpdatePropsArgs) => {\n const id = String(args?.element_id ?? \"\").trim();\n if (!id) return { success: false, error: \"invalid element_id\" };\n\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, args.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 el = findElementById(elements, id);\n if (!el) return { success: false, error: \"element not found\" };\n\n applyPropsPatch(el, args);\n\n if (el.type === \"image\") {\n const anyEl = el as any;\n const alt = String(args.alt ?? anyEl?.props?.alt ?? \"\").trim();\n await resolveUnsplashImageForElement(el, alt);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return { success: true, changed: true, updated_id: id };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -8,7 +8,7 @@ export const CreateNewRouteSchema = {
8
8
  parent_route: {
9
9
  type: Type.STRING,
10
10
  // Accept both "/dashboard" and "dashboard" (caller might omit the leading slash).
11
- pattern: "^(?:/|/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?|[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$",
11
+ pattern: "^(?:/|/(?:[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)$",
12
12
  description: 'The parent route ("/" for app root). Example: "/" or "/dashboard". If you forget the leading "/", it will be assumed (e.g. "dashboard" -> "/dashboard"). NEVER pass empty string, use "/" if not sure about parent route.',
13
13
  },
14
14
  route_name: {
@@ -1 +1 @@
1
- {"version":3,"file":"createNewRoute.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/createNewRoute.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,2HAA2H;IAC7H,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,YAAY,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,kFAAkF;gBAClF,OAAO,EACL,qFAAqF;gBACvF,WAAW,EACT,2NAA2N;aAC9N;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,yFAAyF;aAC5F;SACF;QACD,QAAQ,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;KACzC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nexport const CreateNewRouteSchema = {\n name: \"create_new_route\",\n description:\n \"Creates a new Next.js App Router route folder under /app/<parent_route>/<route_name> with a page.tsx and pageConfig.json.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n parent_route: {\n type: Type.STRING,\n // Accept both \"/dashboard\" and \"dashboard\" (caller might omit the leading slash).\n pattern:\n \"^(?:/|/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?|[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$\",\n description:\n 'The parent route (\"/\" for app root). Example: \"/\" or \"/dashboard\". If you forget the leading \"/\", it will be assumed (e.g. \"dashboard\" -> \"/dashboard\"). NEVER pass empty string, use \"/\" if not sure about parent route.',\n },\n route_name: {\n type: Type.STRING,\n description:\n 'The new route segment to create under the parent route. Example: \"about\" or \"settings\".',\n },\n },\n required: [\"parent_route\", \"route_name\"],\n },\n};\n"]}
1
+ {"version":3,"file":"createNewRoute.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/createNewRoute.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,2HAA2H;IAC7H,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,YAAY,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,kFAAkF;gBAClF,OAAO,EACL,qHAAqH;gBACvH,WAAW,EACT,2NAA2N;aAC9N;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,yFAAyF;aAC5F;SACF;QACD,QAAQ,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;KACzC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nexport const CreateNewRouteSchema = {\n name: \"create_new_route\",\n description:\n \"Creates a new Next.js App Router route folder under /app/<parent_route>/<route_name> with a page.tsx and pageConfig.json.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n parent_route: {\n type: Type.STRING,\n // Accept both \"/dashboard\" and \"dashboard\" (caller might omit the leading slash).\n pattern:\n \"^(?:/|/(?:[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)$\",\n description:\n 'The parent route (\"/\" for app root). Example: \"/\" or \"/dashboard\". If you forget the leading \"/\", it will be assumed (e.g. \"dashboard\" -> \"/dashboard\"). NEVER pass empty string, use \"/\" if not sure about parent route.',\n },\n route_name: {\n type: Type.STRING,\n description:\n 'The new route segment to create under the parent route. Example: \"about\" or \"settings\".',\n },\n },\n required: [\"parent_route\", \"route_name\"],\n },\n};\n"]}
@@ -8,7 +8,7 @@ export const DeleteElementSchema = {
8
8
  route: {
9
9
  type: Type.STRING,
10
10
  // Accept both "/about" and "about" (caller might omit the leading slash).
11
- pattern: "^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)",
11
+ pattern: "^(?:/(?:[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)$",
12
12
  description: "The route to delete the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').",
13
13
  },
14
14
  element_id: {
@@ -1 +1 @@
1
- {"version":3,"file":"deleteElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/deleteElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,uBAAuB;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,wFAAwF;gBAC1F,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;KAClC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const DeleteElementSchema = {\n name: \"delete_element\",\n description: \"Deletes element code.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)\",\n description:\n \"The route to delete the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be deleted.\",\n },\n },\r\n required: [\"route\", \"element_id\"],\r\n },\r\n};\r\n"]}
1
+ {"version":3,"file":"deleteElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/deleteElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,uBAAuB;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,mHAAmH;gBACrH,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;KAClC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const DeleteElementSchema = {\n name: \"delete_element\",\n description: \"Deletes element code.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)$\",\n description:\n \"The route to delete the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be deleted.\",\n },\n },\r\n required: [\"route\", \"element_id\"],\r\n },\r\n};\r\n"]}
@@ -0,0 +1,10 @@
1
+ import { Type } from "@google/genai";
2
+ export declare const GetAvailableRoutesSchema: {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: Type;
7
+ properties: {};
8
+ };
9
+ };
10
+ //# sourceMappingURL=getAvailableRoutes.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getAvailableRoutes.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/getAvailableRoutes.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,wBAAwB;;;;;;;CAOpC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Type } from "@google/genai";
2
+ export const GetAvailableRoutesSchema = {
3
+ name: "get_available_routes",
4
+ description: "Get all available routes in the project.",
5
+ parameters: {
6
+ type: Type.OBJECT,
7
+ properties: {},
8
+ },
9
+ };
10
+ //# sourceMappingURL=getAvailableRoutes.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getAvailableRoutes.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/getAvailableRoutes.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EAAE,0CAA0C;IACvD,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE,EAAE;KACf;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nexport const GetAvailableRoutesSchema = {\n name: \"get_available_routes\",\n description: \"Get all available routes in the project.\",\n parameters: {\n type: Type.OBJECT,\n properties: {},\n },\n};\n"]}
@@ -126,7 +126,7 @@ export const InsertElementSchema = {
126
126
  route: {
127
127
  type: Type.STRING,
128
128
  // Accept both "/about" and "about" (caller might omit the leading slash).
129
- pattern: "^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)",
129
+ pattern: "^(?:/(?:[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)$",
130
130
  description: "The route to insert the element at. Use URL paths with forward slashes only. Examples: '/', '/about', '/pricing'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about'). Never send Windows-style backslashes (e.g. '\\\\') or filesystem paths like 'app/pricing'. Never send empty string.",
131
131
  },
132
132
  parent_id: {
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const ELEMENT_TYPES = [\r\n \"fragment\",\r\n \"div\",\r\n \"text\",\r\n \"image\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"link\",\r\n \"icon\",\r\n] as const;\r\n\r\nconst OnClickActionSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n kind: {\r\n type: Type.STRING,\r\n enum: [\"route\", \"back\", \"reload\", \"external\"],\r\n description:\r\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description:\r\n \"URL to navigate to (used for kind='route' and kind='external').\",\r\n },\r\n replace: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='route': replace history instead of pushing.\",\r\n },\r\n newTab: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='external': open link in a new tab.\",\r\n },\r\n },\r\n required: [\"kind\"],\r\n};\r\n\r\nconst BuilderElementPropsSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n onClick: OnClickActionSchema,\r\n text: {\r\n type: Type.STRING,\r\n description:\r\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description: \"For 'link': the href attribute (defaults to '#').\",\r\n },\r\n placeholder: {\r\n type: Type.STRING,\r\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\r\n },\r\n alt: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\r\n },\r\n target: {\r\n type: Type.STRING,\r\n description: \"For 'link': target attribute (e.g. '_blank').\",\r\n },\r\n rel: {\r\n type: Type.STRING,\r\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\r\n },\r\n value: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\r\n },\r\n type: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\r\n },\r\n\r\n // icon\r\n name: {\r\n type: Type.STRING,\r\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\r\n },\r\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\r\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\r\n strokeWidth: {\r\n type: Type.NUMBER,\r\n description: \"For 'icon': stroke width.\",\r\n },\r\n },\r\n};\r\n\r\n// NOTE: Gemini tool `parameters` schemas reject `$ref`, so true recursion isn't available here.\r\n// We unroll nesting to a reasonable max depth; for deeper trees, insert in multiple steps.\r\nconst buildBuilderElementSchema = (depth: number): any => {\r\n return {\r\n type: Type.OBJECT,\r\n properties: {\r\n type: {\r\n type: Type.STRING,\r\n enum: ELEMENT_TYPES,\r\n description:\r\n \"Element type to render. Use 'text' for <p>, 'image' forn <img>, 'link' for <a>, 'icon' for Lucide icon, 'fragment' renders children only\",\r\n },\r\n className: {\r\n type: Type.STRING,\r\n description: \"Tailwind CSS className (Tailwind only)\",\r\n },\r\n visible: {\r\n type: Type.BOOLEAN,\r\n description: \"Visibility flag\",\r\n },\r\n props: BuilderElementPropsSchema,\r\n children: {\r\n type: Type.ARRAY,\r\n description:\r\n \"Child elements. Each child can itself have children (children[].children[]...)\",\r\n items:\r\n depth > 0\r\n ? buildBuilderElementSchema(depth - 1)\r\n : {\r\n type: Type.OBJECT,\r\n description:\r\n \"Max depth reached. Insert deeper children separately using the returned inserted_id as parent_id\",\r\n },\r\n },\r\n },\r\n required: [\"type\"],\r\n };\r\n};\r\n\r\nexport const BuilderElementSchema: any = buildBuilderElementSchema(4);\r\n\r\nexport const InsertElementSchema = {\n name: \"insert_element\",\n description:\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)\",\n description:\n \"The route to insert the element at. Use URL paths with forward slashes only. Examples: '/', '/about', '/pricing'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about'). Never send Windows-style backslashes (e.g. '\\\\\\\\') or filesystem paths like 'app/pricing'. Never send empty string.\",\n },\n parent_id: {\n type: Type.STRING,\n description: \"The parent id to insert the element at.\",\n },\n before_id: {\n type: Type.STRING,\n description:\n \"Optional. If provided, inserts the new element before the existing child element with this id (within parent_id's children list). If not found, appends at the end.\",\n },\n element: {\n ...BuilderElementSchema,\n description: \"The element to insert.\",\n },\n },\n required: [\"route\", \"parent_id\", \"element\"],\r\n },\r\n};\r\n"]}
1
+ {"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const ELEMENT_TYPES = [\r\n \"fragment\",\r\n \"div\",\r\n \"text\",\r\n \"image\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"link\",\r\n \"icon\",\r\n] as const;\r\n\r\nconst OnClickActionSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n kind: {\r\n type: Type.STRING,\r\n enum: [\"route\", \"back\", \"reload\", \"external\"],\r\n description:\r\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description:\r\n \"URL to navigate to (used for kind='route' and kind='external').\",\r\n },\r\n replace: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='route': replace history instead of pushing.\",\r\n },\r\n newTab: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='external': open link in a new tab.\",\r\n },\r\n },\r\n required: [\"kind\"],\r\n};\r\n\r\nconst BuilderElementPropsSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n onClick: OnClickActionSchema,\r\n text: {\r\n type: Type.STRING,\r\n description:\r\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description: \"For 'link': the href attribute (defaults to '#').\",\r\n },\r\n placeholder: {\r\n type: Type.STRING,\r\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\r\n },\r\n alt: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\r\n },\r\n target: {\r\n type: Type.STRING,\r\n description: \"For 'link': target attribute (e.g. '_blank').\",\r\n },\r\n rel: {\r\n type: Type.STRING,\r\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\r\n },\r\n value: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\r\n },\r\n type: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\r\n },\r\n\r\n // icon\r\n name: {\r\n type: Type.STRING,\r\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\r\n },\r\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\r\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\r\n strokeWidth: {\r\n type: Type.NUMBER,\r\n description: \"For 'icon': stroke width.\",\r\n },\r\n },\r\n};\r\n\r\n// NOTE: Gemini tool `parameters` schemas reject `$ref`, so true recursion isn't available here.\r\n// We unroll nesting to a reasonable max depth; for deeper trees, insert in multiple steps.\r\nconst buildBuilderElementSchema = (depth: number): any => {\r\n return {\r\n type: Type.OBJECT,\r\n properties: {\r\n type: {\r\n type: Type.STRING,\r\n enum: ELEMENT_TYPES,\r\n description:\r\n \"Element type to render. Use 'text' for <p>, 'image' forn <img>, 'link' for <a>, 'icon' for Lucide icon, 'fragment' renders children only\",\r\n },\r\n className: {\r\n type: Type.STRING,\r\n description: \"Tailwind CSS className (Tailwind only)\",\r\n },\r\n visible: {\r\n type: Type.BOOLEAN,\r\n description: \"Visibility flag\",\r\n },\r\n props: BuilderElementPropsSchema,\r\n children: {\r\n type: Type.ARRAY,\r\n description:\r\n \"Child elements. Each child can itself have children (children[].children[]...)\",\r\n items:\r\n depth > 0\r\n ? buildBuilderElementSchema(depth - 1)\r\n : {\r\n type: Type.OBJECT,\r\n description:\r\n \"Max depth reached. Insert deeper children separately using the returned inserted_id as parent_id\",\r\n },\r\n },\r\n },\r\n required: [\"type\"],\r\n };\r\n};\r\n\r\nexport const BuilderElementSchema: any = buildBuilderElementSchema(4);\r\n\r\nexport const InsertElementSchema = {\n name: \"insert_element\",\n description:\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)$\",\n description:\n \"The route to insert the element at. Use URL paths with forward slashes only. Examples: '/', '/about', '/pricing'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about'). Never send Windows-style backslashes (e.g. '\\\\\\\\') or filesystem paths like 'app/pricing'. Never send empty string.\",\n },\n parent_id: {\n type: Type.STRING,\n description: \"The parent id to insert the element at.\",\n },\n before_id: {\n type: Type.STRING,\n description:\n \"Optional. If provided, inserts the new element before the existing child element with this id (within parent_id's children list). If not found, appends at the end.\",\n },\n element: {\n ...BuilderElementSchema,\n description: \"The element to insert.\",\n },\n },\n required: [\"route\", \"parent_id\", \"element\"],\r\n },\r\n};\r\n"]}
@@ -8,7 +8,7 @@ export const UpdateClassNameSchema = {
8
8
  route: {
9
9
  type: Type.STRING,
10
10
  // Accept both "/about" and "about" (caller might omit the leading slash).
11
- pattern: "^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)",
11
+ pattern: "^(?:/(?:[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)$",
12
12
  description: "The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').",
13
13
  },
14
14
  element_id: {
@@ -1 +1 @@
1
- {"version":3,"file":"updateClassName.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateClassName.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,+NAA+N;IACjO,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,wFAAwF;gBAC1F,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC;KAC/C;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const UpdateClassNameSchema = {\n name: \"update_classname\",\n description:\n \"Updates className (only tailwind classes allowed). Give complete className. Prefer semantic token classes (bg-background, text-foreground, border-border, ring-ring, etc.); use update_global_styles to change global tokens.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)\",\n description:\n \"The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be updated.\",\n },\n className: { type: Type.STRING },\r\n },\r\n required: [\"route\", \"element_id\", \"className\"],\r\n },\r\n};\r\n"]}
1
+ {"version":3,"file":"updateClassName.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateClassName.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,+NAA+N;IACjO,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,mHAAmH;gBACrH,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC;KAC/C;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const UpdateClassNameSchema = {\n name: \"update_classname\",\n description:\n \"Updates className (only tailwind classes allowed). Give complete className. Prefer semantic token classes (bg-background, text-foreground, border-border, ring-ring, etc.); use update_global_styles to change global tokens.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)$\",\n description:\n \"The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be updated.\",\n },\n className: { type: Type.STRING },\r\n },\r\n required: [\"route\", \"element_id\", \"className\"],\r\n },\r\n};\r\n"]}
@@ -31,7 +31,7 @@ export const UpdatePropsSchema = {
31
31
  route: {
32
32
  type: Type.STRING,
33
33
  // Accept both "/about" and "about" (caller might omit the leading slash).
34
- pattern: "^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)",
34
+ pattern: "^(?:/(?:[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\]-]+)*)$",
35
35
  description: "The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').",
36
36
  },
37
37
  element_id: {
@@ -1 +1 @@
1
- {"version":3,"file":"updateProps.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateProps.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,IAAI,CAAC,MAAM;IACjB,UAAU,EAAE;QACV,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC;YAC7C,WAAW,EACT,2IAA2I;SAC9I;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,WAAW,EACT,iEAAiE;SACpE;QACD,OAAO,EAAE;YACP,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,WAAW,EAAE,uDAAuD;SACrE;QACD,MAAM,EAAE;YACN,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,WAAW,EAAE,8CAA8C;SAC5D;KACF;IACD,QAAQ,EAAE,CAAC,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,uBAAuB;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,wFAAwF;gBAC1F,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,OAAO,EAAE,mBAAmB;YAC5B,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,4GAA4G;aAC/G;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,mDAAmD;aACjE;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2DAA2D;aACzE;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,gIAAgI;aACnI;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,+CAA+C;aAC7D;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,gDAAgD;aAC9D;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,mEAAmE;aACtE;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,iFAAiF;aACpF;YAED,OAAO;YACP,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2DAA2D;aACzE;YACD,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,yBAAyB,EAAE;YACnE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,2BAA2B,EAAE;YACtE,WAAW,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2BAA2B;aACzC;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;KAClC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nconst OnClickActionSchema = {\n type: Type.OBJECT,\n properties: {\n kind: {\n type: Type.STRING,\n enum: [\"route\", \"back\", \"reload\", \"external\"],\n description:\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\n },\n href: {\n type: Type.STRING,\n description:\n \"URL to navigate to (used for kind='route' and kind='external').\",\n },\n replace: {\n type: Type.BOOLEAN,\n description: \"For kind='route': replace history instead of pushing.\",\n },\n newTab: {\n type: Type.BOOLEAN,\n description: \"For kind='external': open link in a new tab.\",\n },\n },\n required: [\"kind\"],\n};\n\nexport const UpdatePropsSchema = {\n name: \"update_props\",\n description: \"Updates element code.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?)|(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)$)\",\n description:\n \"The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be updated.\",\n },\n onClick: OnClickActionSchema,\n text: {\n type: Type.STRING,\n description:\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\n },\n href: {\n type: Type.STRING,\n description: \"For 'link': the href attribute (defaults to '#').\",\n },\n placeholder: {\n type: Type.STRING,\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\n },\n alt: {\n type: Type.STRING,\n description:\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\n },\n target: {\n type: Type.STRING,\n description: \"For 'link': target attribute (e.g. '_blank').\",\n },\n rel: {\n type: Type.STRING,\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\n },\n value: {\n type: Type.STRING,\n description:\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\n },\n type: {\n type: Type.STRING,\n description:\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\n },\n\n // icon\n name: {\n type: Type.STRING,\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\n },\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\n strokeWidth: {\n type: Type.NUMBER,\n description: \"For 'icon': stroke width.\",\n },\n },\n required: [\"route\", \"element_id\"],\n },\n};\n"]}
1
+ {"version":3,"file":"updateProps.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateProps.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,IAAI,CAAC,MAAM;IACjB,UAAU,EAAE;QACV,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC;YAC7C,WAAW,EACT,2IAA2I;SAC9I;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,WAAW,EACT,iEAAiE;SACpE;QACD,OAAO,EAAE;YACP,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,WAAW,EAAE,uDAAuD;SACrE;QACD,MAAM,EAAE;YACN,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,WAAW,EAAE,8CAA8C;SAC5D;KACF;IACD,QAAQ,EAAE,CAAC,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,uBAAuB;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,0EAA0E;gBAC1E,OAAO,EACL,mHAAmH;gBACrH,WAAW,EACT,6IAA6I;aAChJ;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,OAAO,EAAE,mBAAmB;YAC5B,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,4GAA4G;aAC/G;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,mDAAmD;aACjE;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2DAA2D;aACzE;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,gIAAgI;aACnI;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,+CAA+C;aAC7D;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,gDAAgD;aAC9D;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,mEAAmE;aACtE;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,iFAAiF;aACpF;YAED,OAAO;YACP,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2DAA2D;aACzE;YACD,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,yBAAyB,EAAE;YACnE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,2BAA2B,EAAE;YACtE,WAAW,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,2BAA2B;aACzC;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;KAClC;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nconst OnClickActionSchema = {\n type: Type.OBJECT,\n properties: {\n kind: {\n type: Type.STRING,\n enum: [\"route\", \"back\", \"reload\", \"external\"],\n description:\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\n },\n href: {\n type: Type.STRING,\n description:\n \"URL to navigate to (used for kind='route' and kind='external').\",\n },\n replace: {\n type: Type.BOOLEAN,\n description: \"For kind='route': replace history instead of pushing.\",\n },\n newTab: {\n type: Type.BOOLEAN,\n description: \"For kind='external': open link in a new tab.\",\n },\n },\n required: [\"kind\"],\n};\n\nexport const UpdatePropsSchema = {\n name: \"update_props\",\n description: \"Updates element code.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n // Accept both \"/about\" and \"about\" (caller might omit the leading slash).\n pattern:\n \"^(?:/(?:[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)?|[A-Za-z0-9_.[\\\\\\\\\\]-]+(?:/[A-Za-z0-9_.[\\\\\\\\\\]-]+)*)$\",\n description:\n \"The route to update the element at. Example: '/' or '/about'. If you forget the leading '/', it will be assumed (e.g. 'about' -> '/about').\",\n },\n element_id: {\n type: Type.STRING,\n description: \"The id of the element to be updated.\",\n },\n onClick: OnClickActionSchema,\n text: {\n type: Type.STRING,\n description:\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\n },\n href: {\n type: Type.STRING,\n description: \"For 'link': the href attribute (defaults to '#').\",\n },\n placeholder: {\n type: Type.STRING,\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\n },\n alt: {\n type: Type.STRING,\n description:\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\n },\n target: {\n type: Type.STRING,\n description: \"For 'link': target attribute (e.g. '_blank').\",\n },\n rel: {\n type: Type.STRING,\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\n },\n value: {\n type: Type.STRING,\n description:\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\n },\n type: {\n type: Type.STRING,\n description:\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\n },\n\n // icon\n name: {\n type: Type.STRING,\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\n },\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\n strokeWidth: {\n type: Type.NUMBER,\n description: \"For 'icon': stroke width.\",\n },\n },\n required: [\"route\", \"element_id\"],\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"codegenTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAWrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAgBnC,CAAC"}
1
+ {"version":3,"file":"codegenTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAYrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAiBnC,CAAC"}
@@ -7,6 +7,7 @@ import { InsertElementSchema } from "../schemas/insertElement.schema.js";
7
7
  import { UpdateClassNameSchema } from "../schemas/updateClassName.schema.js";
8
8
  import { UpdatePropsSchema } from "../schemas/updateProps.schema.js";
9
9
  import { UpdateGlobalStylesSchema } from "../schemas/updateGlobalStyles.schema.js";
10
+ import { GetAvailableRoutesSchema } from "../schemas/getAvailableRoutes.schema.js";
10
11
  export const codegenTools = () => {
11
12
  return [
12
13
  {
@@ -19,6 +20,7 @@ export const codegenTools = () => {
19
20
  UpdateClassNameSchema,
20
21
  UpdatePropsSchema,
21
22
  ListDirSchema,
23
+ GetAvailableRoutesSchema,
22
24
  SubmitCodegenDoneSchema,
23
25
  ],
24
26
  },
@@ -1 +1 @@
1
- {"version":3,"file":"codegenTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,wBAAwB;gBACxB,oBAAoB;gBACpB,mBAAmB;gBACnB,mBAAmB;gBACnB,qBAAqB;gBACrB,iBAAiB;gBACjB,aAAa;gBACb,uBAAuB;aACxB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SubmitCodegenDoneSchema } from \"../schemas/submitCodegenDone.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { CreateNewRouteSchema } from \"../schemas/createNewRoute.schema.js\";\nimport { DeleteElementSchema } from \"../schemas/deleteElement.schema.js\";\nimport { InsertElementSchema } from \"../schemas/insertElement.schema.js\";\nimport { UpdateClassNameSchema } from \"../schemas/updateClassName.schema.js\";\nimport { UpdatePropsSchema } from \"../schemas/updateProps.schema.js\";\nimport { UpdateGlobalStylesSchema } from \"../schemas/updateGlobalStyles.schema.js\";\n\nexport const codegenTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n UpdateGlobalStylesSchema,\n CreateNewRouteSchema,\n InsertElementSchema,\n DeleteElementSchema,\n UpdateClassNameSchema,\n UpdatePropsSchema,\n ListDirSchema,\n SubmitCodegenDoneSchema,\n ],\n },\n ];\n};\n"]}
1
+ {"version":3,"file":"codegenTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,wBAAwB;gBACxB,oBAAoB;gBACpB,mBAAmB;gBACnB,mBAAmB;gBACnB,qBAAqB;gBACrB,iBAAiB;gBACjB,aAAa;gBACb,wBAAwB;gBACxB,uBAAuB;aACxB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SubmitCodegenDoneSchema } from \"../schemas/submitCodegenDone.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { CreateNewRouteSchema } from \"../schemas/createNewRoute.schema.js\";\nimport { DeleteElementSchema } from \"../schemas/deleteElement.schema.js\";\nimport { InsertElementSchema } from \"../schemas/insertElement.schema.js\";\nimport { UpdateClassNameSchema } from \"../schemas/updateClassName.schema.js\";\nimport { UpdatePropsSchema } from \"../schemas/updateProps.schema.js\";\nimport { UpdateGlobalStylesSchema } from \"../schemas/updateGlobalStyles.schema.js\";\nimport { GetAvailableRoutesSchema } from \"../schemas/getAvailableRoutes.schema.js\";\n\nexport const codegenTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n UpdateGlobalStylesSchema,\n CreateNewRouteSchema,\n InsertElementSchema,\n DeleteElementSchema,\n UpdateClassNameSchema,\n UpdatePropsSchema,\n ListDirSchema,\n GetAvailableRoutesSchema,\n SubmitCodegenDoneSchema,\n ],\n },\n ];\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"plannerTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/plannerTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAMrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAWnC,CAAC"}
1
+ {"version":3,"file":"plannerTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/plannerTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAOrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAYnC,CAAC"}
@@ -2,6 +2,7 @@ import { ReadFileSchema } from "../schemas/readFile.schema.js";
2
2
  import { SearchSchema } from "../schemas/search.schema.js";
3
3
  import { ListDirSchema } from "../schemas/listDir.schema.js";
4
4
  import { SubmitPlannerTasksSchema } from "../schemas/submitPlannerTasks.schema.js";
5
+ import { GetAvailableRoutesSchema } from "../schemas/getAvailableRoutes.schema.js";
5
6
  export const plannerTools = () => {
6
7
  return [
7
8
  {
@@ -9,6 +10,7 @@ export const plannerTools = () => {
9
10
  ReadFileSchema,
10
11
  SearchSchema,
11
12
  ListDirSchema,
13
+ GetAvailableRoutesSchema,
12
14
  SubmitPlannerTasksSchema,
13
15
  ],
14
16
  },
@@ -1 +1 @@
1
- {"version":3,"file":"plannerTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/plannerTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,YAAY;gBACZ,aAAa;gBACb,wBAAwB;aACzB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SearchSchema } from \"../schemas/search.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { SubmitPlannerTasksSchema } from \"../schemas/submitPlannerTasks.schema.js\";\n\nexport const plannerTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n SearchSchema,\n ListDirSchema,\n SubmitPlannerTasksSchema,\n ],\n },\n ];\n};\n\n"]}
1
+ {"version":3,"file":"plannerTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/plannerTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,YAAY;gBACZ,aAAa;gBACb,wBAAwB;gBACxB,wBAAwB;aACzB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SearchSchema } from \"../schemas/search.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { SubmitPlannerTasksSchema } from \"../schemas/submitPlannerTasks.schema.js\";\nimport { GetAvailableRoutesSchema } from \"../schemas/getAvailableRoutes.schema.js\";\n\nexport const plannerTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n SearchSchema,\n ListDirSchema,\n GetAvailableRoutesSchema,\n SubmitPlannerTasksSchema,\n ],\n },\n ];\n};\n\n"]}
@@ -28,8 +28,8 @@ const isInternalRoutePath = (value) => {
28
28
  return false;
29
29
  if (s.includes("\\"))
30
30
  return false;
31
- // Allow "/" or "/a" or "/a/b-c_d"
32
- return /^\/(?:[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*)?$/.test(s);
31
+ // Allow "/" or "/a" or "/a/b-c_d" or "/product/[id]" or "/blog/[...slug]" or "/blog/[[...slug]]"
32
+ return /^\/(?:[A-Za-z0-9_.[\]-]+(?:\/[A-Za-z0-9_.[\]-]+)*)?$/.test(s);
33
33
  };
34
34
  export const OnClickActionZod = z.discriminatedUnion("kind", [
35
35
  z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"builderElement.zod.js","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nexport const ELEMENT_TYPES = [\n \"fragment\",\n \"div\",\n \"text\",\n \"image\",\n \"button\",\n \"input\",\n \"textarea\",\n \"link\",\n \"icon\",\n] as const;\n\nconst normalizeInternalRoutePath = (value: unknown) => {\n const raw = String(value ?? \"\").trim();\n if (!raw) return \"\";\n const forwardOnly = raw.replace(/\\\\/g, \"/\");\n if (forwardOnly === \"/\") return \"/\";\n if (forwardOnly.startsWith(\"/\")) return forwardOnly;\n // Fallback: if caller forgot the leading slash, assume they meant an app route.\n return `/${forwardOnly}`;\n};\n\nconst isInternalRoutePath = (value: string) => {\n const s = normalizeInternalRoutePath(value);\n if (!s) return false;\n if (s.includes(\"\\\\\")) return false;\n // Allow \"/\" or \"/a\" or \"/a/b-c_d\"\n return /^\\/(?:[A-Za-z0-9_-]+(?:\\/[A-Za-z0-9_-]+)*)?$/.test(s);\n};\n\nexport const OnClickActionZod = z.discriminatedUnion(\"kind\", [\n z.object({\n kind: z.literal(\"route\"),\n href: z.preprocess(\n normalizeInternalRoutePath,\n z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"href must be an internal route path like '/' or '/pricing' (forward slashes only; no backslashes)\",\n }),\n ),\n replace: z.boolean().optional(),\n }),\n z.object({ kind: z.literal(\"back\") }),\n z.object({ kind: z.literal(\"reload\") }),\n z.object({\n kind: z.literal(\"external\"),\n href: z.string().min(1),\n newTab: z.boolean().optional(),\n }),\n]);\n\nexport const BuilderElementZod: z.ZodType<any> = z.object({\n type: z.enum(ELEMENT_TYPES),\n className: z.string().optional(),\n visible: z.boolean().optional(),\n props: z\n .object({\n onClick: OnClickActionZod.optional(),\n text: z.string().optional(),\n href: z.string().optional(),\n placeholder: z.string().optional(),\n alt: z.string().optional(),\n target: z.string().optional(),\n rel: z.string().optional(),\n value: z.string().optional(),\n type: z.string().optional(),\n name: z.string().optional(),\n size: z.number().optional(),\n color: z.string().optional(),\n strokeWidth: z.number().optional(),\n })\n .passthrough()\n .optional(),\n children: z.array(z.lazy(() => BuilderElementZod)).optional(),\n});\n\nexport const InsertElementArgsZod = z.object({\n route: z.preprocess(\n normalizeInternalRoutePath,\n z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"route must be like '/' or '/about' (forward slashes only; no backslashes)\",\n }),\n ),\n parent_id: z.string().min(1),\n before_id: z.string().min(1).optional(),\n element: BuilderElementZod,\n});\n"]}
1
+ {"version":3,"file":"builderElement.zod.js","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nexport const ELEMENT_TYPES = [\n \"fragment\",\n \"div\",\n \"text\",\n \"image\",\n \"button\",\n \"input\",\n \"textarea\",\n \"link\",\n \"icon\",\n] as const;\n\nconst normalizeInternalRoutePath = (value: unknown) => {\n const raw = String(value ?? \"\").trim();\n if (!raw) return \"\";\n const forwardOnly = raw.replace(/\\\\/g, \"/\");\n if (forwardOnly === \"/\") return \"/\";\n if (forwardOnly.startsWith(\"/\")) return forwardOnly;\n // Fallback: if caller forgot the leading slash, assume they meant an app route.\n return `/${forwardOnly}`;\n};\n\nconst isInternalRoutePath = (value: string) => {\n const s = normalizeInternalRoutePath(value);\n if (!s) return false;\n if (s.includes(\"\\\\\")) return false;\n // Allow \"/\" or \"/a\" or \"/a/b-c_d\" or \"/product/[id]\" or \"/blog/[...slug]\" or \"/blog/[[...slug]]\"\n return /^\\/(?:[A-Za-z0-9_.[\\]-]+(?:\\/[A-Za-z0-9_.[\\]-]+)*)?$/.test(s);\n};\n\nexport const OnClickActionZod = z.discriminatedUnion(\"kind\", [\n z.object({\n kind: z.literal(\"route\"),\n href: z.preprocess(\n normalizeInternalRoutePath,\n z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"href must be an internal route path like '/' or '/pricing' (forward slashes only; no backslashes)\",\n }),\n ),\n replace: z.boolean().optional(),\n }),\n z.object({ kind: z.literal(\"back\") }),\n z.object({ kind: z.literal(\"reload\") }),\n z.object({\n kind: z.literal(\"external\"),\n href: z.string().min(1),\n newTab: z.boolean().optional(),\n }),\n]);\n\nexport const BuilderElementZod: z.ZodType<any> = z.object({\n type: z.enum(ELEMENT_TYPES),\n className: z.string().optional(),\n visible: z.boolean().optional(),\n props: z\n .object({\n onClick: OnClickActionZod.optional(),\n text: z.string().optional(),\n href: z.string().optional(),\n placeholder: z.string().optional(),\n alt: z.string().optional(),\n target: z.string().optional(),\n rel: z.string().optional(),\n value: z.string().optional(),\n type: z.string().optional(),\n name: z.string().optional(),\n size: z.number().optional(),\n color: z.string().optional(),\n strokeWidth: z.number().optional(),\n })\n .passthrough()\n .optional(),\n children: z.array(z.lazy(() => BuilderElementZod)).optional(),\n});\n\nexport const InsertElementArgsZod = z.object({\n route: z.preprocess(\n normalizeInternalRoutePath,\n z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"route must be like '/' or '/about' (forward slashes only; no backslashes)\",\n }),\n ),\n parent_id: z.string().min(1),\n before_id: z.string().min(1).optional(),\n element: BuilderElementZod,\n});\n"]}