@vedangiitb/qwintly-core 1.4.8 → 1.4.10

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 (35) hide show
  1. package/dist/ai/generate/gemini.client.d.ts +1 -0
  2. package/dist/ai/generate/gemini.client.d.ts.map +1 -1
  3. package/dist/ai/generate/gemini.client.js +1 -1
  4. package/dist/ai/generate/gemini.client.js.map +1 -1
  5. package/dist/ai/toolLoop/toolLoopRunner.d.ts +6 -0
  6. package/dist/ai/toolLoop/toolLoopRunner.d.ts.map +1 -1
  7. package/dist/ai/toolLoop/toolLoopRunner.js +45 -7
  8. package/dist/ai/toolLoop/toolLoopRunner.js.map +1 -1
  9. package/dist/ai/tools/implementations/factories.d.ts +4 -5
  10. package/dist/ai/tools/implementations/factories.d.ts.map +1 -1
  11. package/dist/ai/tools/implementations/insertElement.impl.d.ts +4 -6
  12. package/dist/ai/tools/implementations/insertElement.impl.d.ts.map +1 -1
  13. package/dist/ai/tools/implementations/insertElement.impl.js +6 -20
  14. package/dist/ai/tools/implementations/insertElement.impl.js.map +1 -1
  15. package/dist/ai/tools/validators/builderElement.zod.d.ts +2 -4
  16. package/dist/ai/tools/validators/builderElement.zod.d.ts.map +1 -1
  17. package/dist/ai/tools/validators/builderElement.zod.js +2 -15
  18. package/dist/ai/tools/validators/builderElement.zod.js.map +1 -1
  19. package/dist/core.d.ts +2 -0
  20. package/dist/core.d.ts.map +1 -1
  21. package/dist/core.js +9 -0
  22. package/dist/core.js.map +1 -1
  23. package/dist/repository/genTokens.repository.d.ts +5 -0
  24. package/dist/repository/genTokens.repository.d.ts.map +1 -0
  25. package/dist/repository/genTokens.repository.js +15 -0
  26. package/dist/repository/genTokens.repository.js.map +1 -0
  27. package/dist/tests/insertUpdate.impl.test.js +9 -10
  28. package/dist/tests/insertUpdate.impl.test.js.map +1 -1
  29. package/dist/tests/toolLoopRunner.routes.test.js +3 -1
  30. package/dist/tests/toolLoopRunner.routes.test.js.map +1 -1
  31. package/dist/tests/toolLoopRunner.tokensPersist.test.d.ts +2 -0
  32. package/dist/tests/toolLoopRunner.tokensPersist.test.d.ts.map +1 -0
  33. package/dist/tests/toolLoopRunner.tokensPersist.test.js +52 -0
  34. package/dist/tests/toolLoopRunner.tokensPersist.test.js.map +1 -0
  35. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { FunctionCallingConfigMode, GoogleGenAI, Tool } from "@google/genai";
2
2
  import type { ZodSchema } from "zod";
3
+ export declare const DEFAULT_MODEL = "gemini-3.1-flash-lite";
3
4
  type AIResponseOptions = {
4
5
  tools?: Tool[];
5
6
  schema?: ZodSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"gemini.client.d.ts","sourceRoot":"","sources":["../../../src/ai/generate/gemini.client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAEzB,WAAW,EACX,IAAI,EACL,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAKrC,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,CAAC;AAEF,qBAAa,qBAAqB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAiB;gBAEzB,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAOnC,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB;CAqC1E"}
1
+ {"version":3,"file":"gemini.client.d.ts","sourceRoot":"","sources":["../../../src/ai/generate/gemini.client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAEzB,WAAW,EACX,IAAI,EACL,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAGrC,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAErD,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,CAAC;AAEF,qBAAa,qBAAqB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAiB;gBAEzB,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAOnC,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB;CAqC1E"}
@@ -1,6 +1,6 @@
1
1
  import { FunctionCallingConfigMode, GoogleGenAI, } from "@google/genai";
2
2
  import { zodToJsonSchema } from "zod-to-json-schema";
3
- const DEFAULT_MODEL = "gemini-2.5-flash-lite";
3
+ export const DEFAULT_MODEL = "gemini-3.1-flash-lite";
4
4
  export class GenerateGeminiReponse {
5
5
  constructor(geminiApiKey, model) {
6
6
  this.model = DEFAULT_MODEL;
@@ -1 +1 @@
1
- {"version":3,"file":"gemini.client.js","sourceRoot":"","sources":["../../../src/ai/generate/gemini.client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAEzB,WAAW,GAEZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAQ9C,MAAM,OAAO,qBAAqB;IAIhC,YAAY,YAAoB,EAAE,KAAc;QAFzC,UAAK,GAAW,aAAa,CAAC;QAGnC,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,OAAgB,EAAE,UAA6B,EAAE;QACvE,MAAM,EACJ,KAAK,EACL,MAAM,EACN,eAAe,GAAG,yBAAyB,CAAC,IAAI,GACjD,GAAG,OAAO,CAAC;QAEZ,MAAM,MAAM,GAA0B,EAAE,CAAC;QAEzC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,MAAM,CAAC,UAAU,GAAG;gBAClB,qBAAqB,EAAE;oBACrB,IAAI,EAAE,eAAe;iBACtB;aACF,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,GAAG,kBAAkB,CAAC;YAC7C,MAAM,CAAC,kBAAkB,GAAG,eAAe,CAAC,MAAa,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;gBAC9C,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,OAAc;gBACxB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;aAClD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,KAAK,CACvB,yBAAyB,GAAG,EAAE,OAAO,IAAI,eAAe,EAAE,CAC3D,CAAC;YACD,OAAe,CAAC,KAAK,GAAG,GAAG,CAAC;YAC7B,MAAM,OAAO,CAAC;QAChB,CAAC;IACH,CAAC;CACF","sourcesContent":["import {\n FunctionCallingConfigMode,\n GenerateContentConfig,\n GoogleGenAI,\n Tool,\n} from \"@google/genai\";\nimport type { ZodSchema } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nconst DEFAULT_MODEL = \"gemini-2.5-flash-lite\";\n\ntype AIResponseOptions = {\n tools?: Tool[];\n schema?: ZodSchema;\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\nexport class GenerateGeminiReponse {\n public gemini: GoogleGenAI;\n public model: string = DEFAULT_MODEL;\n\n constructor(geminiApiKey: string, model?: string) {\n this.gemini = new GoogleGenAI({ apiKey: geminiApiKey });\n if (model) {\n this.model = model;\n }\n }\n\n public async aiResponse(request: unknown, options: AIResponseOptions = {}) {\n const {\n tools,\n schema,\n toolCallingMode = FunctionCallingConfigMode.AUTO,\n } = options;\n\n const config: GenerateContentConfig = {};\n\n if (tools && tools.length > 0) {\n config.tools = tools;\n config.toolConfig = {\n functionCallingConfig: {\n mode: toolCallingMode,\n },\n };\n }\n\n if (schema) {\n config.responseMimeType = \"application/json\";\n config.responseJsonSchema = zodToJsonSchema(schema as any);\n }\n\n try {\n return await this.gemini.models.generateContent({\n model: this.model,\n contents: request as any,\n ...(Object.keys(config).length > 0 && { config }),\n });\n } catch (err: any) {\n const wrapped = new Error(\n `AI generation failed: ${err?.message || \"Unknown error\"}`,\n );\n (wrapped as any).cause = err;\n throw wrapped;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"gemini.client.js","sourceRoot":"","sources":["../../../src/ai/generate/gemini.client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAEzB,WAAW,GAEZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAQrD,MAAM,OAAO,qBAAqB;IAIhC,YAAY,YAAoB,EAAE,KAAc;QAFzC,UAAK,GAAW,aAAa,CAAC;QAGnC,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,OAAgB,EAAE,UAA6B,EAAE;QACvE,MAAM,EACJ,KAAK,EACL,MAAM,EACN,eAAe,GAAG,yBAAyB,CAAC,IAAI,GACjD,GAAG,OAAO,CAAC;QAEZ,MAAM,MAAM,GAA0B,EAAE,CAAC;QAEzC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,MAAM,CAAC,UAAU,GAAG;gBAClB,qBAAqB,EAAE;oBACrB,IAAI,EAAE,eAAe;iBACtB;aACF,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,GAAG,kBAAkB,CAAC;YAC7C,MAAM,CAAC,kBAAkB,GAAG,eAAe,CAAC,MAAa,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;gBAC9C,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,OAAc;gBACxB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;aAClD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,KAAK,CACvB,yBAAyB,GAAG,EAAE,OAAO,IAAI,eAAe,EAAE,CAC3D,CAAC;YACD,OAAe,CAAC,KAAK,GAAG,GAAG,CAAC;YAC7B,MAAM,OAAO,CAAC;QAChB,CAAC;IACH,CAAC;CACF","sourcesContent":["import {\n FunctionCallingConfigMode,\n GenerateContentConfig,\n GoogleGenAI,\n Tool,\n} from \"@google/genai\";\nimport type { ZodSchema } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport const DEFAULT_MODEL = \"gemini-3.1-flash-lite\";\n\ntype AIResponseOptions = {\n tools?: Tool[];\n schema?: ZodSchema;\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\nexport class GenerateGeminiReponse {\n public gemini: GoogleGenAI;\n public model: string = DEFAULT_MODEL;\n\n constructor(geminiApiKey: string, model?: string) {\n this.gemini = new GoogleGenAI({ apiKey: geminiApiKey });\n if (model) {\n this.model = model;\n }\n }\n\n public async aiResponse(request: unknown, options: AIResponseOptions = {}) {\n const {\n tools,\n schema,\n toolCallingMode = FunctionCallingConfigMode.AUTO,\n } = options;\n\n const config: GenerateContentConfig = {};\n\n if (tools && tools.length > 0) {\n config.tools = tools;\n config.toolConfig = {\n functionCallingConfig: {\n mode: toolCallingMode,\n },\n };\n }\n\n if (schema) {\n config.responseMimeType = \"application/json\";\n config.responseJsonSchema = zodToJsonSchema(schema as any);\n }\n\n try {\n return await this.gemini.models.generateContent({\n model: this.model,\n contents: request as any,\n ...(Object.keys(config).length > 0 && { config }),\n });\n } catch (err: any) {\n const wrapped = new Error(\n `AI generation failed: ${err?.message || \"Unknown error\"}`,\n );\n (wrapped as any).cause = err;\n throw wrapped;\n }\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { FunctionCallingConfigMode, Tool } from "@google/genai";
2
+ import type { GenTokensRepository } from "../../repository/genTokens.repository.js";
2
3
  import { EventType } from "../../types/events.js";
3
4
  import { ToolLoopContextPolicy } from "./toolLoopContext.js";
4
5
  export type ToolLoopResult = {
@@ -38,6 +39,11 @@ export type RunToolLoopOptions = {
38
39
  aiCallAutoRetryBaseMs?: number;
39
40
  aiCallAutoRetryMaxMs?: number;
40
41
  persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>;
42
+ tokenPersistence?: {
43
+ repository: Pick<GenTokensRepository, "persistGenTokens">;
44
+ sessionId: string;
45
+ model: string;
46
+ };
41
47
  };
42
48
  export declare function runToolLoop(options: RunToolLoopOptions): Promise<ToolLoopResult>;
43
49
  //# sourceMappingURL=toolLoopRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolLoopRunner.d.ts","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAe,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAM/D,OAAO,EAML,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,aAAa,EAAE,GAAG,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,KACE,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE,CAAC;AAEF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAglBzB"}
1
+ {"version":3,"file":"toolLoopRunner.d.ts","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAEpF,OAAO,EAAe,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAM/D,OAAO,EAML,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,aAAa,EAAE,GAAG,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,yBAAyB,CAAC;CAC7C,KACE,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,gBAAgB,CAAC,EAAE;QACjB,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;QAC1D,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CA+nBzB"}
@@ -3,16 +3,43 @@ import fs from "node:fs/promises";
3
3
  import { persistToolCall } from "../../services/toolcallPersist.service.js";
4
4
  import { EVENT_TYPES } from "../../types/events.js";
5
5
  import { STYLE_TOKEN_KEYS } from "../../types/styleConfig.js";
6
+ import { getAvailableRoutes } from "../tools/helpers/pageConfigJson.helpers.js";
6
7
  import { createWorkspaceToolImpls } from "../tools/implementations/factories.js";
7
8
  import { parsePlannerTasksUnknown } from "./plannerTaskParser.js";
8
- import { getAvailableRoutes } from "../tools/helpers/pageConfigJson.helpers.js";
9
9
  import { compactForModel, DEFAULT_CONTEXT_POLICY, normalizeReadFileArgs, redactFunctionCallArgs, } from "./toolLoopContext.js";
10
10
  import { aiCallWithRetry, buildToolStatusMessage, recordToolEvent, serializeError, } from "./toolLoopRunnerUtils.js";
11
11
  export async function runToolLoop(options) {
12
12
  const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
13
13
  const styleTokenKeySet = new Set(STYLE_TOKEN_KEYS);
14
14
  const { initialContents, tools, workspaceRoot, maxSteps = 30, toolCallingMode = FunctionCallingConfigMode.ANY, terminalToolNames = [], keepFullTrace = true, contextPolicy, aiCall, logger, applyPatchAutoRetryMax = 2, aiCallAutoRetryMax = 3, // must have it to try 3 times as gemini errors a lot due to high demand sometimes
15
- aiCallAutoRetryBaseMs = 400, aiCallAutoRetryMaxMs = 10000, persistResponse, } = options;
15
+ aiCallAutoRetryBaseMs = 400, aiCallAutoRetryMaxMs = 10000, persistResponse, tokenPersistence, } = options;
16
+ const extractUsageTokenCounts = (rawResponse) => {
17
+ const usage = rawResponse?.usageMetadata;
18
+ const promptTokenCount = usage?.promptTokenCount;
19
+ const candidatesTokenCount = usage?.candidatesTokenCount;
20
+ const inputTokens = Number(promptTokenCount);
21
+ const outputTokens = Number(candidatesTokenCount);
22
+ if (!Number.isFinite(inputTokens) || inputTokens < 0)
23
+ return null;
24
+ if (!Number.isFinite(outputTokens) || outputTokens < 0)
25
+ return null;
26
+ return { inputTokens, outputTokens };
27
+ };
28
+ let totalInputTokens = 0;
29
+ let totalOutputTokens = 0;
30
+ let sawAnyTokenUsage = false;
31
+ const persistTokensOnce = async () => {
32
+ if (!tokenPersistence)
33
+ return;
34
+ if (!sawAnyTokenUsage)
35
+ return;
36
+ try {
37
+ await tokenPersistence.repository.persistGenTokens(tokenPersistence.sessionId, totalInputTokens, totalOutputTokens, tokenPersistence.model);
38
+ }
39
+ catch (err) {
40
+ console.error("Tool loop: failed to persist gen tokens", err);
41
+ }
42
+ };
16
43
  const nodeFs = {
17
44
  readFile: async (absolutePath) => fs.readFile(absolutePath, "utf-8"),
18
45
  writeFile: async (absolutePath, content) => fs.writeFile(absolutePath, content ?? "", "utf-8"),
@@ -62,12 +89,12 @@ export async function runToolLoop(options) {
62
89
  return result;
63
90
  },
64
91
  insert_element: async (args) => {
65
- const route = String(args.route ?? "");
66
- const parent_id = String(args.parent_id ?? "");
67
- const element = args.element;
68
- const result = await impls.insertElementImpl(route, parent_id, element);
92
+ const result = await impls.insertElementImpl(args);
69
93
  if (!result.success) {
70
- const available = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });
94
+ const available = await getAvailableRoutes({
95
+ workspaceRoot,
96
+ fs: nodeFs,
97
+ });
71
98
  return {
72
99
  success: false,
73
100
  error: `insert_element failed: ${result.error}. Available routes are: ${JSON.stringify(available)}. If you intend to create a new route, create it using the 'create_new_route' tool.`,
@@ -199,8 +226,17 @@ export async function runToolLoop(options) {
199
226
  });
200
227
  }
201
228
  }
229
+ {
230
+ const usage = extractUsageTokenCounts(response);
231
+ if (usage) {
232
+ sawAnyTokenUsage = true;
233
+ totalInputTokens += usage.inputTokens;
234
+ totalOutputTokens += usage.outputTokens;
235
+ }
236
+ }
202
237
  const functionCalls = response.functionCalls ?? [];
203
238
  if (functionCalls.length === 0) {
239
+ await persistTokensOnce();
204
240
  return {
205
241
  contents: keepFullTrace ? fullTraceContents : modelContents,
206
242
  modelContents,
@@ -487,6 +523,7 @@ export async function runToolLoop(options) {
487
523
  toolResultRaw,
488
524
  });
489
525
  if (terminalToolNames.includes(name)) {
526
+ await persistTokensOnce();
490
527
  return {
491
528
  contents: keepFullTrace ? fullTraceContents : modelContents,
492
529
  modelContents,
@@ -497,6 +534,7 @@ export async function runToolLoop(options) {
497
534
  }
498
535
  }
499
536
  }
537
+ await persistTokensOnce();
500
538
  return {
501
539
  contents: keepFullTrace ? fullTraceContents : modelContents,
502
540
  modelContents,
@@ -1 +1 @@
1
- {"version":3,"file":"toolLoopRunner.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAQ,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAa,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,GAGvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,cAAc,GACf,MAAM,0BAA0B,CAAC;AAgDlC,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAA2B;IAE3B,MAAM,aAAa,GAAG,CAAC,KAAc,EAAoC,EAAE,CACzE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAEvE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,gBAAuC,CACxC,CAAC;IAEF,MAAM,EACJ,eAAe,EACf,KAAK,EACL,aAAa,EACb,QAAQ,GAAG,EAAE,EACb,eAAe,GAAG,yBAAyB,CAAC,GAAG,EAC/C,iBAAiB,GAAG,EAAE,EACtB,aAAa,GAAG,IAAI,EACpB,aAAa,EACb,MAAM,EACN,MAAM,EACN,sBAAsB,GAAG,CAAC,EAC1B,kBAAkB,GAAG,CAAC,EAAE,kFAAkF;IAC1G,qBAAqB,GAAG,GAAG,EAC3B,oBAAoB,GAAG,KAAM,EAC7B,eAAe,GAChB,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAAW;QACrB,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;QACpE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,CACzC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,CAAC;QACpD,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC5B,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACpE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;QACnD,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CACjC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;KACnD,CAAC;IAEF,MAAM,KAAK,GAAG,wBAAwB,CAAC;QACrC,aAAa;QACb,EAAE,EAAE,MAAM;KACX,CAAC,CAAC;IAEH,MAAM,YAAY,GAAgD;QAChE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACxB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACrC,MAAM,SAAS,GACb,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtE,MAAM,OAAO,GACX,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACnE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CACnB,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAC1E,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CACrC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,EACvB,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CACxB,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC;QACrB,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,CAAC;QACrB,CAAC;QACD,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CACpB,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QACvD,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;YACxD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YACtE,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAQ,IAAI,CAAC,OAAO,CAAC;YAClC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACxE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC1E,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,0BAA0B,MAAM,CAAC,KAAK,2BAA2B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,qFAAqF;oBACtL,gBAAgB,EAAE,SAAS;iBAC5B,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,KAAK,GAAQ,IAAI,CAAC,KAAK,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC;gBACzC,KAAK;gBACL,UAAU;gBACV,GAAG,KAAK;aACT,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,mBAAmB,CAC5C,KAAK,EACL,UAAU,EACV,UAAU,CACX,CAAC;YACF,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACnC,CAAC;QACD,mBAAmB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACpC,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;SAC3C,CAAC;QACF,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACnC,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QAChD,CAAC;KACF,CAAC;IAEF,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,MAAM,GAAoC;QAC9C,GAAG,sBAAsB;QACzB,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;KACzB,CAAC;IAEF,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;IAC9D,MAAM,yBAAyB,GAAG;QAChC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE;YACL;gBACE,IAAI,EACF,GAAG,sBAAsB,IAAI;oBAC7B,4BAA4B,QAAQ,wCAAwC;oBAC5E,uDAAuD;oBACvD,sGAAsG;aACzG;SACF;KACF,CAAC;IAEF,MAAM,iBAAiB,GAAU,aAAa;QAC5C,CAAC,CAAC,CAAC,GAAG,eAAe,EAAE,yBAAyB,CAAC;QACjD,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,aAAa,GAAU,CAAC,GAAG,eAAe,EAAE,yBAAyB,CAAC,CAAC;IAC3E,MAAM,kBAAkB,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,CAAC,QAAa,EAAE,SAAc,EAAE,EAAE;QACjD,IAAI,aAAa;YAAE,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,CAAC,SAAc,EAAE,EAAE;QACvC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3C,aAAa,GAAG,eAAe,CAAC;YAC9B,YAAY,EAAE,kBAAkB;YAChC,aAAa;YACb,UAAU;YACV,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE;gBAC3C,WAAW;gBACX,IAAI,EAAE,IAAI,GAAG,CAAC;aACf,CAAC,CAAC;QACL,CAAC;QAED,IAAI,QAAuC,CAAC;QAC5C,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,eAAe,CAAC;gBAC/B,MAAM;gBACN,OAAO,EAAE,aAAa;gBACtB,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;gBACnC,QAAQ,EAAE,kBAAkB;gBAC5B,WAAW,EAAE,qBAAqB;gBAClC,UAAU,EAAE,oBAAoB;gBAChC,IAAI,EAAE,IAAI,GAAG,CAAC;gBACd,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CACJ,iEAAiE,EACjE,WAAW,CAAC,UAAU,CACvB,CAAC;YACF,OAAO,CAAC,KAAK,CAAC,iDAAiD,EAAE,GAAG,EAAE;gBACpE,IAAI,EAAE,IAAI,GAAG,CAAC;gBACd,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC;aAC3B,CAAC,CAAC;YAEH,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACnE,MAAM,wBAAwB,GAAG;gBAC/B,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE;oBACL;wBACE,IAAI,EACF,oHAAoH;4BACpH,UAAU,OAAO,IAAI;4BACrB,iHAAiH;qBACpH;iBACF;aACF,CAAC;YACF,IAAI,aAAa;gBAAE,iBAAiB,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACpE,SAAS;QACX,CAAC;QAED,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,EAAE;oBAC1D,IAAI,EAAE,IAAI,GAAG,CAAC;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC;QACnD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa;gBAC3D,aAAa;gBACb,SAAS,EAAE,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBACvC,KAAK,EAAE,IAAI,GAAG,CAAC;aAChB,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE;YAC1B,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAE,QAAgB,EAAE,UAAU,CAAC;oBAC7D,CAAC,CAAG,QAAgB,CAAC,UAAoB;oBACzC,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;gBAC9C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAe,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;gBACtC,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;oBACpB,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,CAAC;oBAC3B,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;oBAClB,MAAM,GAAG,GAAG,CAAC,EAAE,gBAAgB,IAAI,CAAC,EAAE,iBAAiB,CAAC;oBACxD,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,EAAE,CAAC;wBAC7D,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;oBACnB,CAAC;gBACH,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,GAAG,EAAkB,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;YACtE,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;YAC1D,MAAM,gBAAgB,GAAuB,CAAC,GAAG,EAAE;gBACjD,MAAM,MAAM,GACT,IAAY,EAAE,iBAAiB,IAAK,IAAY,EAAE,gBAAgB,CAAC;gBACtE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM;oBAAE,OAAO,MAAM,CAAC;gBACxD,MAAM,EAAE,GAAI,IAAY,EAAE,EAAE,CAAC;gBAC7B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBACpD,OAAO,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/B,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC,EAAE,CAAC;YAEL,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,CACJ,kFAAkF,EAClF,WAAW,CAAC,UAAU,CACvB,CAAC;gBACF,MAAM,oBAAoB,GAAG;oBAC3B,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE;wBACL;4BACE,IAAI,EACF,0FAA0F;gCAC1F,wEAAwE;gCACxE,aAAa,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;yBAC7D;qBACF;iBACF,CAAC;gBACF,IAAI,aAAa;oBAAE,iBAAiB,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAChE,aAAa,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBACzC,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,oBAAoB,GAAG,CAAC,OAAO;gBACnC,CAAC,CAAC;oBACE,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,8BAA8B,IAAI,IAAI;oBAC7C,YAAY,EAAE;wBACZ,IAAI,EAAE,yBAAyB;wBAC/B,OAAO,EAAE,8BAA8B,IAAI,IAAI;qBAChD;iBACF;gBACH,CAAC,CAAC,IAAI,CAAC;YAET,IAAI,aAAa,GAA4B,IAAI,CAAC;YAClD,IAAI,YAAY,GAIL,IAAI,CAAC;YAChB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;gBACzB,MAAM,UAAU,GAAG,qBAAqB,CACtC,aAAa,EACb,MAAM,CAAC,uBAAuB,CAC/B,CAAC;gBACF,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC;gBACzC,YAAY,GAAG;oBACb,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,GAAG,EAAE,UAAU,CAAC,GAAG;oBACnB,SAAS,EAAE,UAAU,CAAC,SAAS;iBAChC,CAAC;YACJ,CAAC;YAED,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;gBACpC,8EAA8E;gBAC9E,gFAAgF;gBAChF,MAAM,WAAW,GAAI,aAAqB,EAAE,MAAM,CAAC;gBACnD,MAAM,UAAU,GAA4B,EAAE,CAAC;gBAE/C,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;wBACjD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;4BAAE,SAAS;wBACvC,IAAI,OAAO,CAAC,KAAK,QAAQ;4BAAE,SAAS;wBACpC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;oBACpB,CAAC;gBACH,CAAC;gBAED,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,EAAE,CAAC;oBACzD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;wBAAE,SAAS;oBACvC,IAAI,OAAO,CAAC,KAAK,QAAQ;wBAAE,SAAS;oBACpC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;gBAED,aAAa,GAAG,UAAU,CAAC;YAC7B,CAAC;YAED,MAAM,CACJ,sBAAsB,CAAC,IAAI,EAAE,aAAa,EAAE,YAAY,CAAC,EACzD,WAAW,CAAC,YAAY,CACzB,CAAC;YAEF,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YAE9D,MAAM,gBAAgB,GAAG;gBACvB,YAAY,EAAE;oBACZ,IAAI;oBACJ,IAAI,EAAE,aAAa;iBACpB;gBACD,GAAG,CAAC,gBAAgB;oBAClB,CAAC,CAAC;wBACE,gBAAgB,EAAE,gBAAgB;wBAClC,iBAAiB,EAAE,gBAAgB;qBACpC;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;YAEF,MAAM,qBAAqB,GAAG;gBAC5B,YAAY,EAAE;oBACZ,IAAI;oBACJ,IAAI,EAAE,SAAS;iBAChB;gBACD,GAAG,CAAC,gBAAgB;oBAClB,CAAC,CAAC;wBACE,gBAAgB,EAAE,gBAAgB;wBAClC,iBAAiB,EAAE,gBAAgB;qBACpC;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;YAEF,MAAM,aAAa,GAAG;gBACpB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE;oBACL;wBACE,GAAG,gBAAgB;qBACpB;iBACF;aACF,CAAC;YAEF,MAAM,cAAc,GAAG;gBACrB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE;oBACL;wBACE,GAAG,qBAAqB;qBACzB;iBACF;aACF,CAAC;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,cAAc,CAAC,CAAC;YAChC,CAAC;YAED,IAAI,aAAsB,CAAC;YAC3B,IAAI,oBAAoB,EAAE,CAAC;gBACzB,aAAa,GAAG,oBAAoB,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;wBACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7D,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CACxB,CAAC;wBACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;4BAC1B,aAAa,GAAG;gCACd,OAAO,EAAE,KAAK;gCACd,KAAK,EAAE,2CAA2C;gCAClD,YAAY,EAAE;oCACZ,IAAI,EAAE,2BAA2B;oCACjC,OAAO,EACL,0FAA0F;iCAC7F;gCACD,IAAI,EAAE,wFAAwF;6BAC/F,CAAC;wBACJ,CAAC;6BAAM,CAAC;4BACN,aAAa,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;wBAC/C,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,aAAa,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,YAAY,IAAI,SAAS,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;oBAC1D,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,EAAE;wBAC7C,IAAI,EAAE,IAAI;wBACV,IAAI,EAAE,IAAI,GAAG,CAAC;qBACf,CAAC,CAAC;oBACH,aAAa,GAAG;wBACd,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACvD,YAAY,EAAE,cAAc,CAAC,GAAG,CAAC;wBACjC,IAAI,EAAE,iGAAiG;qBACxG,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,IAAI,UAAU,GAAY,aAAa,CAAC;YAExC,IAAI,IAAI,KAAK,WAAW,IAAI,YAAY,EAAE,CAAC;gBACzC,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAE9C,MAAM,WAAW,GACd,aAAqB,EAAE,IAAI,KAAK,MAAM;oBACrC,CAAC,CAAE,aAAqB,EAAE,IAAI;oBAC9B,CAAC,CAAC,SAAS,CAAC;gBAChB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBAC9B,4EAA4E;oBAC5E,UAAU,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;gBAC3C,CAAC;qBAAM,CAAC;oBACN,MAAM,UAAU,GACd,OAAQ,aAAqB,EAAE,OAAO,KAAK,QAAQ;wBACjD,CAAC,CAAC,MAAM,CAAE,aAAqB,CAAC,OAAO,CAAC;wBACxC,CAAC,CAAC,OAAO,aAAa,KAAK,QAAQ;4BACjC,CAAC,CAAC,aAAa;4BACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,IAAI,CAAC,CAAC;oBAE9C,UAAU,GAAG;wBACX,IAAI;wBACJ,UAAU,EAAE,YAAY,CAAC,KAAK;wBAC9B,QAAQ,EAAE,YAAY,CAAC,GAAG;wBAC1B,SAAS,EAAE,YAAY,CAAC,SAAS;wBACjC,OAAO,EAAE,UAAU;wBACnB,IAAI,EAAE,YAAY,CAAC,SAAS;4BAC1B,CAAC,CAAC,aAAa,MAAM,CAAC,uBAAuB,gDAAgD;4BAC7F,CAAC,CAAC,SAAS;qBACd,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,EAAE;oBAC3D,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI,GAAG,CAAC;iBACf,CAAC,CAAC;YACL,CAAC;YAED,MAAM,YAAY,GAAG;gBACnB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE;oBACL;wBACE,gBAAgB,EAAE;4BAChB,IAAI;4BACJ,QAAQ,EAAE,UAAU;yBACrB;qBACF;iBACF;aACF,CAAC;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACvC,CAAC;YACD,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAEjC,IACE,IAAI,KAAK,aAAa;gBACrB,UAAkB,EAAE,OAAO,KAAK,KAAK;gBACtC,sBAAsB,GAAG,CAAC;gBAC1B,oBAAoB,GAAG,sBAAsB,EAC7C,CAAC;gBACD,oBAAoB,IAAI,CAAC,CAAC;gBAE1B,MAAM,KAAK,GAAG,MAAM,CAAE,UAAkB,EAAE,KAAK,IAAI,eAAe,CAAC,CAAC;gBACpE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAE,UAAkB,EAAE,KAAK,EAAE,KAAK,CAAC;oBACjE,CAAC,CAAG,UAAkB,CAAC,KAAK,CAAC,KAGxB;oBACL,CAAC,CAAC,EAAE,CAAC;gBAEP,MAAM,SAAS,GACb,UAAU,CAAC,MAAM,GAAG,CAAC;oBACnB,CAAC,CAAC,qDAAqD,UAAU;yBAC5D,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;yBACX,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,SAAS,MAAM,CACxC,CAAC,CAAC,IAAI,IAAI,EAAE,CACb,eAAe,CACnB;yBACA,IAAI,CAAC,MAAM,CAAC,EAAE;oBACnB,CAAC,CAAC,EAAE,CAAC;gBAET,MAAM,gBAAgB,GAAG;oBACvB,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE;wBACL;4BACE,IAAI,EACF,+BAA+B,oBAAoB,IAAI,sBAAsB,MAAM,KAAK,IAAI;gCAC5F,6DAA6D;gCAC7D,uFAAuF;gCACvF,SAAS;yBACZ;qBACF;iBACF,CAAC;gBAEF,IAAI,aAAa;oBAAE,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC5D,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACvC,CAAC;YAED,eAAe,CAAC;gBACd,UAAU;gBACV,IAAI;gBACJ,aAAa;gBACb,SAAS;gBACT,YAAY;gBACZ,UAAU;gBACV,aAAa;aACd,CAAC,CAAC;YAEH,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,OAAO;oBACL,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa;oBAC3D,aAAa;oBACb,SAAS,EAAE,EAAE;oBACb,KAAK,EAAE,IAAI,GAAG,CAAC;oBACf,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE;iBACrE,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa;QAC3D,aAAa;QACb,SAAS,EAAE,+BAA+B,QAAQ,IAAI;QACtD,KAAK,EAAE,QAAQ;KAChB,CAAC;AACJ,CAAC","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport fs from \"node:fs/promises\";\nimport { persistToolCall } from \"../../services/toolcallPersist.service.js\";\nimport { EVENT_TYPES, EventType } from \"../../types/events.js\";\nimport { STYLE_TOKEN_KEYS } from \"../../types/styleConfig.js\";\nimport { createWorkspaceToolImpls } from \"../tools/implementations/factories.js\";\nimport { CoreFs } from \"../tools/implementations/workspaceDeps.js\";\nimport { parsePlannerTasksUnknown } from \"./plannerTaskParser.js\";\nimport { getAvailableRoutes } from \"../tools/helpers/pageConfigJson.helpers.js\";\nimport {\n compactForModel,\n DEFAULT_CONTEXT_POLICY,\n normalizeReadFileArgs,\n redactFunctionCallArgs,\n ToolEvent,\n ToolLoopContextPolicy,\n} from \"./toolLoopContext.js\";\nimport {\n aiCallWithRetry,\n buildToolStatusMessage,\n recordToolEvent,\n serializeError,\n} from \"./toolLoopRunnerUtils.js\";\n\nexport type ToolLoopResult = {\n contents: any[];\n modelContents: any[];\n finalText: string;\n steps: number;\n terminalCall?: {\n name: string;\n args: Record<string, unknown>;\n response: unknown;\n };\n};\n\nexport type Logger = (message: string, eventType: EventType) => Promise<void>;\n\nexport type AiCallResponse = {\n functionCalls?: any[];\n text?: string;\n};\n\nexport type AiCallFn = (\n request: unknown,\n options: {\n tools?: Tool[];\n model?: string;\n toolCallingMode?: FunctionCallingConfigMode;\n },\n) => Promise<AiCallResponse>;\n\nexport type RunToolLoopOptions = {\n initialContents: any[];\n tools: Tool[];\n workspaceRoot: string;\n maxSteps?: number;\n toolCallingMode?: FunctionCallingConfigMode;\n terminalToolNames?: string[];\n keepFullTrace?: boolean;\n contextPolicy?: ToolLoopContextPolicy;\n aiCall: AiCallFn;\n logger: Logger;\n applyPatchAutoRetryMax?: number;\n aiCallAutoRetryMax?: number;\n aiCallAutoRetryBaseMs?: number;\n aiCallAutoRetryMaxMs?: number;\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>;\n};\n\nexport async function runToolLoop(\n options: RunToolLoopOptions,\n): Promise<ToolLoopResult> {\n const isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const styleTokenKeySet = new Set<string>(\n STYLE_TOKEN_KEYS as unknown as string[],\n );\n\n const {\n initialContents,\n tools,\n workspaceRoot,\n maxSteps = 30,\n toolCallingMode = FunctionCallingConfigMode.ANY,\n terminalToolNames = [],\n keepFullTrace = true,\n contextPolicy,\n aiCall,\n logger,\n applyPatchAutoRetryMax = 2,\n aiCallAutoRetryMax = 3, // must have it to try 3 times as gemini errors a lot due to high demand sometimes\n aiCallAutoRetryBaseMs = 400,\n aiCallAutoRetryMaxMs = 10_000,\n persistResponse,\n } = options;\n\n const nodeFs: CoreFs = {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n };\n\n const impls = createWorkspaceToolImpls({\n workspaceRoot,\n fs: nodeFs,\n });\n\n const toolHandlers: Record<string, (args: any) => Promise<any>> = {\n read_file: async (args) => {\n const path = String(args.path ?? \"\");\n const startLine =\n args.start_line === undefined ? undefined : Number(args.start_line);\n const endLine =\n args.end_line === undefined ? undefined : Number(args.end_line);\n const content = await impls.readFileImpl(path, startLine, endLine);\n return { path, content };\n },\n write_file: (args) =>\n impls.writeFileImpl(String(args.path ?? \"\"), String(args.content ?? \"\")),\n list_dir: async (args) => {\n const content = await impls.listDirImpl(\n String(args.path ?? \"\"),\n Number(args.depth ?? 1),\n );\n return { content };\n },\n search: async (args) => {\n const results = await impls.searchImpl(String(args.search_query ?? \"\"));\n return { results };\n },\n apply_patch: (args) =>\n impls.applyPatchImpl(String(args.patch_string ?? \"\")),\n update_global_styles: async (args) => {\n const result = await impls.updateGlobalStylesImpl(args);\n return result;\n },\n create_new_route: async (args) => {\n const parentRoute = String(args.parent_route ?? \"\");\n const routeName = String(args.route_name ?? \"\");\n const result = await impls.createNewRouteImpl(parentRoute, routeName);\n return result;\n },\n delete_element: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const result = await impls.deleteElementImpl(route, element_id);\n return result;\n },\n insert_element: async (args) => {\n const route = String(args.route ?? \"\");\n const parent_id = String(args.parent_id ?? \"\");\n const element: any = args.element;\n const result = await impls.insertElementImpl(route, parent_id, element);\n if (!result.success) {\n const available = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });\n return {\n success: false,\n error: `insert_element failed: ${result.error}. Available routes are: ${JSON.stringify(available)}. If you intend to create a new route, create it using the 'create_new_route' tool.`,\n available_routes: available,\n };\n }\n return result;\n },\n update_props: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const props: any = args.props;\n const result = await impls.updatePropsImpl({\n route,\n element_id,\n ...props,\n });\n return result;\n },\n update_classname: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const class_name = String(args.class_name ?? \"\");\n const result = await impls.updateClassNameImpl(\n route,\n element_id,\n class_name,\n );\n return result;\n },\n get_available_routes: async (args) => {\n const routes = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });\n return { success: true, routes };\n },\n submit_codegen_done: async (args) => ({\n success: true,\n summary: String(args.summary ?? \"\").trim(),\n }),\n submit_planner_tasks: async (args) => {\n const tasks = parsePlannerTasksUnknown(args.planner_tasks);\n return { success: true, count: tasks.length };\n },\n };\n\n if (typeof aiCall !== \"function\") {\n throw new Error(\"Tool loop: aiCall is required.\");\n }\n\n const policy: Required<ToolLoopContextPolicy> = {\n ...DEFAULT_CONTEXT_POLICY,\n ...(contextPolicy ?? {}),\n };\n\n const toolEvents: ToolEvent[] = [];\n let applyPatchRetryCount = 0;\n\n const EXECUTION_GUIDE_MARKER = \"TOOL_LOOP_EXECUTION_GUIDE_V1\";\n const executionGuideInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `${EXECUTION_GUIDE_MARKER}\\n` +\n `Execution limit: At most ${maxSteps} assistant turn(s) in this tool loop. ` +\n `One turn = one assistant response in the tool loop.\\n` +\n `Complete the task in as few turns as possible and avoid unnecessary actions. Prioritize correctness.`,\n },\n ],\n };\n\n const fullTraceContents: any[] = keepFullTrace\n ? [...initialContents, executionGuideInstruction]\n : [];\n let modelContents: any[] = [...initialContents, executionGuideInstruction];\n const pinnedInitialCount = initialContents.length + 1;\n const pushBoth = (fullItem: any, modelItem: any) => {\n if (keepFullTrace) fullTraceContents.push(fullItem);\n modelContents.push(modelItem);\n };\n const pushModelOnly = (modelItem: any) => {\n modelContents.push(modelItem);\n };\n\n for (let step = 0; step < maxSteps; step++) {\n modelContents = compactForModel({\n initialCount: pinnedInitialCount,\n modelContents,\n toolEvents,\n policy,\n });\n\n if (policy.logApproxModelChars) {\n const approxChars = JSON.stringify(modelContents).length;\n console.log(\"Tool loop: approx model chars\", {\n approxChars,\n step: step + 1,\n });\n }\n\n let response: Awaited<ReturnType<AiCallFn>>;\n try {\n response = await aiCallWithRetry({\n aiCall,\n request: modelContents,\n options: { tools, toolCallingMode },\n retryMax: aiCallAutoRetryMax,\n retryBaseMs: aiCallAutoRetryBaseMs,\n retryMaxMs: aiCallAutoRetryMaxMs,\n step: step + 1,\n logger,\n });\n } catch (err) {\n logger(\n \"Tool loop: AI provider error; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n console.error(\"Tool loop: aiCall failed (provider/server side)\", err, {\n step: step + 1,\n error: serializeError(err),\n });\n\n const message =\n err instanceof Error ? err.message : JSON.stringify(err ?? null);\n const providerErrorInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `AI provider error (server-side). Do NOT clear or restart context; continue from the existing conversation state.\\n` +\n `Error: ${message}\\n` +\n `Next: retry the last request using the same context. If you were about to call tools, resend a valid tool call.`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(providerErrorInstruction);\n continue;\n }\n\n if (persistResponse) {\n try {\n await persistResponse(modelContents, response);\n } catch (err) {\n console.error(\"Tool loop: failed to persist response\", err, {\n step: step + 1,\n });\n }\n }\n\n const functionCalls = response.functionCalls ?? [];\n if (functionCalls.length === 0) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: (response.text ?? \"\").trim(),\n steps: step + 1,\n };\n }\n\n const signatureById = (() => {\n try {\n const candidates = Array.isArray((response as any)?.candidates)\n ? ((response as any).candidates as any[])\n : [];\n const parts = candidates?.[0]?.content?.parts;\n const arr = Array.isArray(parts) ? (parts as any[]) : [];\n const map = new Map<string, string>();\n for (const p of arr) {\n const fc = p?.functionCall;\n const id = fc?.id;\n const sig = p?.thoughtSignature ?? p?.thought_signature;\n if (typeof id === \"string\" && typeof sig === \"string\" && sig) {\n map.set(id, sig);\n }\n }\n return map;\n } catch {\n return new Map<string, string>();\n }\n })();\n\n for (let callIndex = 0; callIndex < functionCalls.length; callIndex++) {\n const call = functionCalls[callIndex];\n const name = call.name?.toString() ?? \"\";\n const args = (call.args ?? {}) as Record<string, unknown>;\n const thoughtSignature: string | undefined = (() => {\n const direct =\n (call as any)?.thought_signature ?? (call as any)?.thoughtSignature;\n if (typeof direct === \"string\" && direct) return direct;\n const id = (call as any)?.id;\n if (typeof id === \"string\" && signatureById.has(id)) {\n return signatureById.get(id);\n }\n return undefined;\n })();\n\n if (!name) {\n logger(\n \"Tool loop: malformed function call from model; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n const malformedInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `Malformed function call received (missing tool name). Do NOT clear or restart context.\\n` +\n `Resend a single valid tool call with a non-empty name and JSON args.\\n` +\n `Bad call: ${JSON.stringify(call ?? null).slice(0, 1500)}`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(malformedInstruction);\n modelContents.push(malformedInstruction);\n continue;\n }\n\n const handler = toolHandlers[name];\n const handlerMissingResult = !handler\n ? {\n success: false,\n error: `No handler registered for \"${name}\".`,\n error_detail: {\n name: \"MissingToolHandlerError\",\n message: `No handler registered for \"${name}\".`,\n },\n }\n : null;\n\n let effectiveArgs: Record<string, unknown> = args;\n let readFileMeta: {\n start: number;\n end: number;\n wasCapped: boolean;\n } | null = null;\n if (name === \"read_file\") {\n const normalized = normalizeReadFileArgs(\n effectiveArgs,\n policy.readFileDefaultMaxLines,\n );\n effectiveArgs = normalized.effectiveArgs;\n readFileMeta = {\n start: normalized.start,\n end: normalized.end,\n wasCapped: normalized.wasCapped,\n };\n }\n\n if (name === \"update_global_styles\") {\n // Be forgiving: models sometimes include a legacy \"tokens\" key or other junk.\n // We accept the call as long as at least one valid token key/value is provided.\n const tokensMaybe = (effectiveArgs as any)?.tokens;\n const normalized: Record<string, unknown> = {};\n\n if (isPlainObject(tokensMaybe)) {\n for (const [k, v] of Object.entries(tokensMaybe)) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n }\n\n for (const [k, v] of Object.entries(effectiveArgs ?? {})) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n\n effectiveArgs = normalized;\n }\n\n logger(\n buildToolStatusMessage(name, effectiveArgs, readFileMeta),\n EVENT_TYPES.STEP_STARTED,\n );\n\n const modelArgs = redactFunctionCallArgs(name, effectiveArgs);\n\n const functionCallPart = {\n functionCall: {\n name,\n args: effectiveArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const functionCallPartModel = {\n functionCall: {\n name,\n args: modelArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const assistantFull = {\n role: \"model\",\n parts: [\n {\n ...functionCallPart,\n },\n ],\n };\n\n const assistantModel = {\n role: \"model\",\n parts: [\n {\n ...functionCallPartModel,\n },\n ],\n };\n\n if (keepFullTrace) {\n pushBoth(assistantFull, assistantModel);\n } else {\n pushModelOnly(assistantModel);\n }\n\n let toolResultRaw: unknown;\n if (handlerMissingResult) {\n toolResultRaw = handlerMissingResult;\n } else {\n try {\n if (name === \"update_global_styles\") {\n const flatKeys = Object.keys(effectiveArgs ?? {}).filter((k) =>\n styleTokenKeySet.has(k),\n );\n if (flatKeys.length === 0) {\n toolResultRaw = {\n success: false,\n error: \"must include at least one token key/value\",\n error_detail: {\n name: \"InvalidToolArgumentsError\",\n message:\n 'update_global_styles requires at least one token key/value (e.g. { radius: \"0.75rem\" }).',\n },\n note: \"Resend update_global_styles with at least one token key/value, or skip this tool call.\",\n };\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } catch (err) {\n logger(`AI tool: ${name} failed`, EVENT_TYPES.STEP_ERROR);\n console.error(\"Tool loop: handler threw\", err, {\n tool: name,\n step: step + 1,\n });\n toolResultRaw = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n error_detail: serializeError(err),\n note: \"Tool handler threw. Inspect error_detail and retry with corrected args or a different approach.\",\n };\n }\n }\n let toolResult: unknown = toolResultRaw;\n\n if (name === \"read_file\" && readFileMeta) {\n const path = String(effectiveArgs.path ?? \"\");\n\n const jsonPayload =\n (toolResultRaw as any)?.kind === \"json\"\n ? (toolResultRaw as any)?.json\n : undefined;\n if (jsonPayload !== undefined) {\n // Token-efficient: return JSON as structured data (no double-stringifying).\n toolResult = { path, json: jsonPayload };\n } else {\n const rawContent =\n typeof (toolResultRaw as any)?.content === \"string\"\n ? String((toolResultRaw as any).content)\n : typeof toolResultRaw === \"string\"\n ? toolResultRaw\n : JSON.stringify(toolResultRaw ?? null);\n\n toolResult = {\n path,\n start_line: readFileMeta.start,\n end_line: readFileMeta.end,\n truncated: readFileMeta.wasCapped,\n content: rawContent,\n note: readFileMeta.wasCapped\n ? `Capped to ${policy.readFileDefaultMaxLines} lines. Request more with start_line/end_line.`\n : undefined,\n };\n }\n }\n\n try {\n await persistToolCall(name, modelArgs, toolResult);\n } catch (err) {\n console.error(\"Tool loop: failed to persist tool call\", err, {\n tool: name,\n step: step + 1,\n });\n }\n\n const responseFull = {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name,\n response: toolResult,\n },\n },\n ],\n };\n\n if (keepFullTrace) {\n fullTraceContents.push(responseFull);\n }\n modelContents.push(responseFull);\n\n if (\n name === \"apply_patch\" &&\n (toolResult as any)?.success === false &&\n applyPatchAutoRetryMax > 0 &&\n applyPatchRetryCount < applyPatchAutoRetryMax\n ) {\n applyPatchRetryCount += 1;\n\n const error = String((toolResult as any)?.error ?? \"unknown error\");\n const debugFiles = Array.isArray((toolResult as any)?.debug?.files)\n ? ((toolResult as any).debug.files as Array<{\n path?: string;\n head?: string;\n }>)\n : [];\n\n const debugText =\n debugFiles.length > 0\n ? `\\n\\nFILE SNAPSHOTS (for regenerating the patch):\\n${debugFiles\n .slice(0, 3)\n .map(\n (f) =>\n `--- ${String(f.path ?? \"\")} ---\\n${String(\n f.head ?? \"\",\n )}\\n--- end ---`,\n )\n .join(\"\\n\\n\")}`\n : \"\";\n\n const retryInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `apply_patch failed (attempt ${applyPatchRetryCount}/${applyPatchAutoRetryMax}): ${error}\\n` +\n `Regenerate a patch that matches the current file contents. ` +\n `For large rewrites, prefer write_file(path, content) or Delete+Add instead of Update.` +\n debugText,\n },\n ],\n };\n\n if (keepFullTrace) fullTraceContents.push(retryInstruction);\n modelContents.push(retryInstruction);\n }\n\n recordToolEvent({\n toolEvents,\n name,\n effectiveArgs,\n modelArgs,\n readFileMeta,\n toolResult,\n toolResultRaw,\n });\n\n if (terminalToolNames.includes(name)) {\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: \"\",\n steps: step + 1,\n terminalCall: { name, args: effectiveArgs, response: toolResultRaw },\n };\n }\n }\n }\n\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: `Stopped: max steps reached (${maxSteps}).`,\n steps: maxSteps,\n };\n}\n"]}
1
+ {"version":3,"file":"toolLoopRunner.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport fs from \"node:fs/promises\";\nimport type { GenTokensRepository } from \"../../repository/genTokens.repository.js\";\nimport { persistToolCall } from \"../../services/toolcallPersist.service.js\";\nimport { EVENT_TYPES, EventType } from \"../../types/events.js\";\nimport { STYLE_TOKEN_KEYS } from \"../../types/styleConfig.js\";\nimport { getAvailableRoutes } from \"../tools/helpers/pageConfigJson.helpers.js\";\nimport { createWorkspaceToolImpls } from \"../tools/implementations/factories.js\";\nimport { CoreFs } from \"../tools/implementations/workspaceDeps.js\";\nimport { parsePlannerTasksUnknown } from \"./plannerTaskParser.js\";\nimport {\n compactForModel,\n DEFAULT_CONTEXT_POLICY,\n normalizeReadFileArgs,\n redactFunctionCallArgs,\n ToolEvent,\n ToolLoopContextPolicy,\n} from \"./toolLoopContext.js\";\nimport {\n aiCallWithRetry,\n buildToolStatusMessage,\n recordToolEvent,\n serializeError,\n} from \"./toolLoopRunnerUtils.js\";\n\nexport type ToolLoopResult = {\n contents: any[];\n modelContents: any[];\n finalText: string;\n steps: number;\n terminalCall?: {\n name: string;\n args: Record<string, unknown>;\n response: unknown;\n };\n};\n\nexport type Logger = (message: string, eventType: EventType) => Promise<void>;\n\nexport type AiCallResponse = {\n functionCalls?: any[];\n text?: string;\n};\n\nexport type AiCallFn = (\n request: unknown,\n options: {\n tools?: Tool[];\n model?: string;\n toolCallingMode?: FunctionCallingConfigMode;\n },\n) => Promise<AiCallResponse>;\n\nexport type RunToolLoopOptions = {\n initialContents: any[];\n tools: Tool[];\n workspaceRoot: string;\n maxSteps?: number;\n toolCallingMode?: FunctionCallingConfigMode;\n terminalToolNames?: string[];\n keepFullTrace?: boolean;\n contextPolicy?: ToolLoopContextPolicy;\n aiCall: AiCallFn;\n logger: Logger;\n applyPatchAutoRetryMax?: number;\n aiCallAutoRetryMax?: number;\n aiCallAutoRetryBaseMs?: number;\n aiCallAutoRetryMaxMs?: number;\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>;\n tokenPersistence?: {\n repository: Pick<GenTokensRepository, \"persistGenTokens\">;\n sessionId: string;\n model: string;\n };\n};\n\nexport async function runToolLoop(\n options: RunToolLoopOptions,\n): Promise<ToolLoopResult> {\n const isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n const styleTokenKeySet = new Set<string>(\n STYLE_TOKEN_KEYS as unknown as string[],\n );\n\n const {\n initialContents,\n tools,\n workspaceRoot,\n maxSteps = 30,\n toolCallingMode = FunctionCallingConfigMode.ANY,\n terminalToolNames = [],\n keepFullTrace = true,\n contextPolicy,\n aiCall,\n logger,\n applyPatchAutoRetryMax = 2,\n aiCallAutoRetryMax = 3, // must have it to try 3 times as gemini errors a lot due to high demand sometimes\n aiCallAutoRetryBaseMs = 400,\n aiCallAutoRetryMaxMs = 10_000,\n persistResponse,\n tokenPersistence,\n } = options;\n\n const extractUsageTokenCounts = (rawResponse: unknown) => {\n const usage = (rawResponse as any)?.usageMetadata;\n const promptTokenCount = usage?.promptTokenCount;\n const candidatesTokenCount = usage?.candidatesTokenCount;\n\n const inputTokens = Number(promptTokenCount);\n const outputTokens = Number(candidatesTokenCount);\n\n if (!Number.isFinite(inputTokens) || inputTokens < 0) return null;\n if (!Number.isFinite(outputTokens) || outputTokens < 0) return null;\n\n return { inputTokens, outputTokens };\n };\n\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let sawAnyTokenUsage = false;\n\n const persistTokensOnce = async () => {\n if (!tokenPersistence) return;\n if (!sawAnyTokenUsage) return;\n\n try {\n await tokenPersistence.repository.persistGenTokens(\n tokenPersistence.sessionId,\n totalInputTokens,\n totalOutputTokens,\n tokenPersistence.model,\n );\n } catch (err) {\n console.error(\"Tool loop: failed to persist gen tokens\", err);\n }\n };\n\n const nodeFs: CoreFs = {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n };\n\n const impls = createWorkspaceToolImpls({\n workspaceRoot,\n fs: nodeFs,\n });\n\n const toolHandlers: Record<string, (args: any) => Promise<any>> = {\n read_file: async (args) => {\n const path = String(args.path ?? \"\");\n const startLine =\n args.start_line === undefined ? undefined : Number(args.start_line);\n const endLine =\n args.end_line === undefined ? undefined : Number(args.end_line);\n const content = await impls.readFileImpl(path, startLine, endLine);\n return { path, content };\n },\n write_file: (args) =>\n impls.writeFileImpl(String(args.path ?? \"\"), String(args.content ?? \"\")),\n list_dir: async (args) => {\n const content = await impls.listDirImpl(\n String(args.path ?? \"\"),\n Number(args.depth ?? 1),\n );\n return { content };\n },\n search: async (args) => {\n const results = await impls.searchImpl(String(args.search_query ?? \"\"));\n return { results };\n },\n apply_patch: (args) =>\n impls.applyPatchImpl(String(args.patch_string ?? \"\")),\n update_global_styles: async (args) => {\n const result = await impls.updateGlobalStylesImpl(args);\n return result;\n },\n create_new_route: async (args) => {\n const parentRoute = String(args.parent_route ?? \"\");\n const routeName = String(args.route_name ?? \"\");\n const result = await impls.createNewRouteImpl(parentRoute, routeName);\n return result;\n },\n delete_element: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const result = await impls.deleteElementImpl(route, element_id);\n return result;\n },\n insert_element: async (args) => {\n const result = await impls.insertElementImpl(args);\n if (!result.success) {\n const available = await getAvailableRoutes({\n workspaceRoot,\n fs: nodeFs,\n });\n return {\n success: false,\n error: `insert_element failed: ${result.error}. Available routes are: ${JSON.stringify(available)}. If you intend to create a new route, create it using the 'create_new_route' tool.`,\n available_routes: available,\n };\n }\n return result;\n },\n update_props: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const props: any = args.props;\n const result = await impls.updatePropsImpl({\n route,\n element_id,\n ...props,\n });\n return result;\n },\n update_classname: async (args) => {\n const route = String(args.route ?? \"\");\n const element_id = String(args.element_id ?? \"\");\n const class_name = String(args.class_name ?? \"\");\n const result = await impls.updateClassNameImpl(\n route,\n element_id,\n class_name,\n );\n return result;\n },\n get_available_routes: async (args) => {\n const routes = await getAvailableRoutes({ workspaceRoot, fs: nodeFs });\n return { success: true, routes };\n },\n submit_codegen_done: async (args) => ({\n success: true,\n summary: String(args.summary ?? \"\").trim(),\n }),\n submit_planner_tasks: async (args) => {\n const tasks = parsePlannerTasksUnknown(args.planner_tasks);\n return { success: true, count: tasks.length };\n },\n };\n\n if (typeof aiCall !== \"function\") {\n throw new Error(\"Tool loop: aiCall is required.\");\n }\n\n const policy: Required<ToolLoopContextPolicy> = {\n ...DEFAULT_CONTEXT_POLICY,\n ...(contextPolicy ?? {}),\n };\n\n const toolEvents: ToolEvent[] = [];\n let applyPatchRetryCount = 0;\n\n const EXECUTION_GUIDE_MARKER = \"TOOL_LOOP_EXECUTION_GUIDE_V1\";\n const executionGuideInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `${EXECUTION_GUIDE_MARKER}\\n` +\n `Execution limit: At most ${maxSteps} assistant turn(s) in this tool loop. ` +\n `One turn = one assistant response in the tool loop.\\n` +\n `Complete the task in as few turns as possible and avoid unnecessary actions. Prioritize correctness.`,\n },\n ],\n };\n\n const fullTraceContents: any[] = keepFullTrace\n ? [...initialContents, executionGuideInstruction]\n : [];\n let modelContents: any[] = [...initialContents, executionGuideInstruction];\n const pinnedInitialCount = initialContents.length + 1;\n const pushBoth = (fullItem: any, modelItem: any) => {\n if (keepFullTrace) fullTraceContents.push(fullItem);\n modelContents.push(modelItem);\n };\n const pushModelOnly = (modelItem: any) => {\n modelContents.push(modelItem);\n };\n\n for (let step = 0; step < maxSteps; step++) {\n modelContents = compactForModel({\n initialCount: pinnedInitialCount,\n modelContents,\n toolEvents,\n policy,\n });\n\n if (policy.logApproxModelChars) {\n const approxChars = JSON.stringify(modelContents).length;\n console.log(\"Tool loop: approx model chars\", {\n approxChars,\n step: step + 1,\n });\n }\n\n let response: Awaited<ReturnType<AiCallFn>>;\n try {\n response = await aiCallWithRetry({\n aiCall,\n request: modelContents,\n options: { tools, toolCallingMode },\n retryMax: aiCallAutoRetryMax,\n retryBaseMs: aiCallAutoRetryBaseMs,\n retryMaxMs: aiCallAutoRetryMaxMs,\n step: step + 1,\n logger,\n });\n } catch (err) {\n logger(\n \"Tool loop: AI provider error; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n console.error(\"Tool loop: aiCall failed (provider/server side)\", err, {\n step: step + 1,\n error: serializeError(err),\n });\n\n const message =\n err instanceof Error ? err.message : JSON.stringify(err ?? null);\n const providerErrorInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `AI provider error (server-side). Do NOT clear or restart context; continue from the existing conversation state.\\n` +\n `Error: ${message}\\n` +\n `Next: retry the last request using the same context. If you were about to call tools, resend a valid tool call.`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(providerErrorInstruction);\n continue;\n }\n\n if (persistResponse) {\n try {\n await persistResponse(modelContents, response);\n } catch (err) {\n console.error(\"Tool loop: failed to persist response\", err, {\n step: step + 1,\n });\n }\n }\n\n {\n const usage = extractUsageTokenCounts(response);\n if (usage) {\n sawAnyTokenUsage = true;\n totalInputTokens += usage.inputTokens;\n totalOutputTokens += usage.outputTokens;\n }\n }\n\n const functionCalls = response.functionCalls ?? [];\n if (functionCalls.length === 0) {\n await persistTokensOnce();\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: (response.text ?? \"\").trim(),\n steps: step + 1,\n };\n }\n\n const signatureById = (() => {\n try {\n const candidates = Array.isArray((response as any)?.candidates)\n ? ((response as any).candidates as any[])\n : [];\n const parts = candidates?.[0]?.content?.parts;\n const arr = Array.isArray(parts) ? (parts as any[]) : [];\n const map = new Map<string, string>();\n for (const p of arr) {\n const fc = p?.functionCall;\n const id = fc?.id;\n const sig = p?.thoughtSignature ?? p?.thought_signature;\n if (typeof id === \"string\" && typeof sig === \"string\" && sig) {\n map.set(id, sig);\n }\n }\n return map;\n } catch {\n return new Map<string, string>();\n }\n })();\n\n for (let callIndex = 0; callIndex < functionCalls.length; callIndex++) {\n const call = functionCalls[callIndex];\n const name = call.name?.toString() ?? \"\";\n const args = (call.args ?? {}) as Record<string, unknown>;\n const thoughtSignature: string | undefined = (() => {\n const direct =\n (call as any)?.thought_signature ?? (call as any)?.thoughtSignature;\n if (typeof direct === \"string\" && direct) return direct;\n const id = (call as any)?.id;\n if (typeof id === \"string\" && signatureById.has(id)) {\n return signatureById.get(id);\n }\n return undefined;\n })();\n\n if (!name) {\n logger(\n \"Tool loop: malformed function call from model; preserving context and continuing\",\n EVENT_TYPES.STEP_ERROR,\n );\n const malformedInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `Malformed function call received (missing tool name). Do NOT clear or restart context.\\n` +\n `Resend a single valid tool call with a non-empty name and JSON args.\\n` +\n `Bad call: ${JSON.stringify(call ?? null).slice(0, 1500)}`,\n },\n ],\n };\n if (keepFullTrace) fullTraceContents.push(malformedInstruction);\n modelContents.push(malformedInstruction);\n continue;\n }\n\n const handler = toolHandlers[name];\n const handlerMissingResult = !handler\n ? {\n success: false,\n error: `No handler registered for \"${name}\".`,\n error_detail: {\n name: \"MissingToolHandlerError\",\n message: `No handler registered for \"${name}\".`,\n },\n }\n : null;\n\n let effectiveArgs: Record<string, unknown> = args;\n let readFileMeta: {\n start: number;\n end: number;\n wasCapped: boolean;\n } | null = null;\n if (name === \"read_file\") {\n const normalized = normalizeReadFileArgs(\n effectiveArgs,\n policy.readFileDefaultMaxLines,\n );\n effectiveArgs = normalized.effectiveArgs;\n readFileMeta = {\n start: normalized.start,\n end: normalized.end,\n wasCapped: normalized.wasCapped,\n };\n }\n\n if (name === \"update_global_styles\") {\n // Be forgiving: models sometimes include a legacy \"tokens\" key or other junk.\n // We accept the call as long as at least one valid token key/value is provided.\n const tokensMaybe = (effectiveArgs as any)?.tokens;\n const normalized: Record<string, unknown> = {};\n\n if (isPlainObject(tokensMaybe)) {\n for (const [k, v] of Object.entries(tokensMaybe)) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n }\n\n for (const [k, v] of Object.entries(effectiveArgs ?? {})) {\n if (!styleTokenKeySet.has(k)) continue;\n if (typeof v !== \"string\") continue;\n normalized[k] = v;\n }\n\n effectiveArgs = normalized;\n }\n\n logger(\n buildToolStatusMessage(name, effectiveArgs, readFileMeta),\n EVENT_TYPES.STEP_STARTED,\n );\n\n const modelArgs = redactFunctionCallArgs(name, effectiveArgs);\n\n const functionCallPart = {\n functionCall: {\n name,\n args: effectiveArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const functionCallPartModel = {\n functionCall: {\n name,\n args: modelArgs,\n },\n ...(thoughtSignature\n ? {\n thoughtSignature: thoughtSignature,\n thought_signature: thoughtSignature,\n }\n : {}),\n };\n\n const assistantFull = {\n role: \"model\",\n parts: [\n {\n ...functionCallPart,\n },\n ],\n };\n\n const assistantModel = {\n role: \"model\",\n parts: [\n {\n ...functionCallPartModel,\n },\n ],\n };\n\n if (keepFullTrace) {\n pushBoth(assistantFull, assistantModel);\n } else {\n pushModelOnly(assistantModel);\n }\n\n let toolResultRaw: unknown;\n if (handlerMissingResult) {\n toolResultRaw = handlerMissingResult;\n } else {\n try {\n if (name === \"update_global_styles\") {\n const flatKeys = Object.keys(effectiveArgs ?? {}).filter((k) =>\n styleTokenKeySet.has(k),\n );\n if (flatKeys.length === 0) {\n toolResultRaw = {\n success: false,\n error: \"must include at least one token key/value\",\n error_detail: {\n name: \"InvalidToolArgumentsError\",\n message:\n 'update_global_styles requires at least one token key/value (e.g. { radius: \"0.75rem\" }).',\n },\n note: \"Resend update_global_styles with at least one token key/value, or skip this tool call.\",\n };\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } else {\n toolResultRaw = await handler(effectiveArgs);\n }\n } catch (err) {\n logger(`AI tool: ${name} failed`, EVENT_TYPES.STEP_ERROR);\n console.error(\"Tool loop: handler threw\", err, {\n tool: name,\n step: step + 1,\n });\n toolResultRaw = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n error_detail: serializeError(err),\n note: \"Tool handler threw. Inspect error_detail and retry with corrected args or a different approach.\",\n };\n }\n }\n let toolResult: unknown = toolResultRaw;\n\n if (name === \"read_file\" && readFileMeta) {\n const path = String(effectiveArgs.path ?? \"\");\n\n const jsonPayload =\n (toolResultRaw as any)?.kind === \"json\"\n ? (toolResultRaw as any)?.json\n : undefined;\n if (jsonPayload !== undefined) {\n // Token-efficient: return JSON as structured data (no double-stringifying).\n toolResult = { path, json: jsonPayload };\n } else {\n const rawContent =\n typeof (toolResultRaw as any)?.content === \"string\"\n ? String((toolResultRaw as any).content)\n : typeof toolResultRaw === \"string\"\n ? toolResultRaw\n : JSON.stringify(toolResultRaw ?? null);\n\n toolResult = {\n path,\n start_line: readFileMeta.start,\n end_line: readFileMeta.end,\n truncated: readFileMeta.wasCapped,\n content: rawContent,\n note: readFileMeta.wasCapped\n ? `Capped to ${policy.readFileDefaultMaxLines} lines. Request more with start_line/end_line.`\n : undefined,\n };\n }\n }\n\n try {\n await persistToolCall(name, modelArgs, toolResult);\n } catch (err) {\n console.error(\"Tool loop: failed to persist tool call\", err, {\n tool: name,\n step: step + 1,\n });\n }\n\n const responseFull = {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name,\n response: toolResult,\n },\n },\n ],\n };\n\n if (keepFullTrace) {\n fullTraceContents.push(responseFull);\n }\n modelContents.push(responseFull);\n\n if (\n name === \"apply_patch\" &&\n (toolResult as any)?.success === false &&\n applyPatchAutoRetryMax > 0 &&\n applyPatchRetryCount < applyPatchAutoRetryMax\n ) {\n applyPatchRetryCount += 1;\n\n const error = String((toolResult as any)?.error ?? \"unknown error\");\n const debugFiles = Array.isArray((toolResult as any)?.debug?.files)\n ? ((toolResult as any).debug.files as Array<{\n path?: string;\n head?: string;\n }>)\n : [];\n\n const debugText =\n debugFiles.length > 0\n ? `\\n\\nFILE SNAPSHOTS (for regenerating the patch):\\n${debugFiles\n .slice(0, 3)\n .map(\n (f) =>\n `--- ${String(f.path ?? \"\")} ---\\n${String(\n f.head ?? \"\",\n )}\\n--- end ---`,\n )\n .join(\"\\n\\n\")}`\n : \"\";\n\n const retryInstruction = {\n role: \"user\",\n parts: [\n {\n text:\n `apply_patch failed (attempt ${applyPatchRetryCount}/${applyPatchAutoRetryMax}): ${error}\\n` +\n `Regenerate a patch that matches the current file contents. ` +\n `For large rewrites, prefer write_file(path, content) or Delete+Add instead of Update.` +\n debugText,\n },\n ],\n };\n\n if (keepFullTrace) fullTraceContents.push(retryInstruction);\n modelContents.push(retryInstruction);\n }\n\n recordToolEvent({\n toolEvents,\n name,\n effectiveArgs,\n modelArgs,\n readFileMeta,\n toolResult,\n toolResultRaw,\n });\n\n if (terminalToolNames.includes(name)) {\n await persistTokensOnce();\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: \"\",\n steps: step + 1,\n terminalCall: { name, args: effectiveArgs, response: toolResultRaw },\n };\n }\n }\n }\n\n await persistTokensOnce();\n return {\n contents: keepFullTrace ? fullTraceContents : modelContents,\n modelContents,\n finalText: `Stopped: max steps reached (${maxSteps}).`,\n steps: maxSteps,\n };\n}\n"]}
@@ -155,15 +155,13 @@ export declare const createWorkspaceToolImpls: (deps: SearchDeps) => {
155
155
  deleted_id: string;
156
156
  error?: undefined;
157
157
  }>;
158
- insertElementImpl: (routeOrArgs: string | Record<string, unknown>, parentId?: string, element?: import("../../../types/elements.js").BuilderElement | any[], beforeId?: string) => Promise<{
158
+ insertElementImpl: (routeOrArgs: string | Record<string, unknown>, parentId?: string, inputElements?: any[], beforeId?: string) => Promise<{
159
159
  success: boolean;
160
160
  error: string;
161
161
  error_detail: import("zod").ZodFlattenedError<{
162
162
  route: string;
163
163
  parent_id: string;
164
- before_id?: string | undefined;
165
- element?: any;
166
- elements?: {
164
+ elements: {
167
165
  id: string;
168
166
  parentId: string;
169
167
  type: "input" | "fragment" | "div" | "text" | "image" | "button" | "textarea" | "link" | "icon";
@@ -197,7 +195,8 @@ export declare const createWorkspaceToolImpls: (deps: SearchDeps) => {
197
195
  color?: string | undefined;
198
196
  strokeWidth?: number | undefined;
199
197
  } | undefined;
200
- }[] | undefined;
198
+ }[];
199
+ before_id?: string | undefined;
201
200
  }, string>;
202
201
  changed?: undefined;
203
202
  inserted_id?: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/factories.ts"],"names":[],"mappings":"AAMA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,eAAO,MAAM,wBAAwB,GAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BxD,CAAC"}
1
+ {"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/factories.ts"],"names":[],"mappings":"AAMA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,eAAO,MAAM,wBAAwB,GAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BxD,CAAC"}
@@ -1,14 +1,11 @@
1
- import type { BuilderElement } from "../../../types/elements.js";
2
1
  import { type WorkspaceDeps } from "./workspaceDeps.js";
3
- export declare const createInsertElementImpl: (deps: WorkspaceDeps) => (routeOrArgs: string | Record<string, unknown>, parentId?: string, element?: BuilderElement | any[], beforeId?: string) => Promise<{
2
+ export declare const createInsertElementImpl: (deps: WorkspaceDeps) => (routeOrArgs: string | Record<string, unknown>, parentId?: string, inputElements?: any[], beforeId?: string) => Promise<{
4
3
  success: boolean;
5
4
  error: string;
6
5
  error_detail: import("zod").ZodFlattenedError<{
7
6
  route: string;
8
7
  parent_id: string;
9
- before_id?: string | undefined;
10
- element?: any;
11
- elements?: {
8
+ elements: {
12
9
  id: string;
13
10
  parentId: string;
14
11
  type: "input" | "fragment" | "div" | "text" | "image" | "button" | "textarea" | "link" | "icon";
@@ -42,7 +39,8 @@ export declare const createInsertElementImpl: (deps: WorkspaceDeps) => (routeOrA
42
39
  color?: string | undefined;
43
40
  strokeWidth?: number | undefined;
44
41
  } | undefined;
45
- }[] | undefined;
42
+ }[];
43
+ before_id?: string | undefined;
46
44
  }, string>;
47
45
  changed?: undefined;
48
46
  inserted_id?: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAWjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAyCxD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAIvD,aAAa,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,WAAW,MAAM,EACjB,UAAU,cAAc,GAAG,GAAG,EAAE,EAChC,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6HpB,CAAC"}
1
+ {"version":3,"file":"insertElement.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAyCxD,eAAO,MAAM,uBAAuB,GAAI,MAAM,aAAa,MAIvD,aAAa,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,WAAW,MAAM,EACjB,gBAAgB,GAAG,EAAE,EACrB,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHpB,CAAC"}
@@ -36,15 +36,14 @@ function reconstructTree(flatElements) {
36
36
  }
37
37
  export const createInsertElementImpl = (deps) => {
38
38
  const { workspaceRoot, fs } = deps;
39
- return async (routeOrArgs, parentId, element, beforeId) => {
39
+ return async (routeOrArgs, parentId, inputElements, beforeId) => {
40
40
  const rawArgs = typeof routeOrArgs === "object" && routeOrArgs !== null
41
41
  ? routeOrArgs
42
42
  : {
43
43
  route: routeOrArgs,
44
44
  parent_id: parentId,
45
45
  before_id: beforeId,
46
- element: !Array.isArray(element) ? element : undefined,
47
- elements: Array.isArray(element) ? element : undefined,
46
+ elements: inputElements,
48
47
  };
49
48
  const parsedArgs = InsertElementArgsZod.safeParse(rawArgs);
50
49
  if (!parsedArgs.success) {
@@ -96,26 +95,13 @@ export const createInsertElementImpl = (deps) => {
96
95
  ensureElementIds(elements, existingIds);
97
96
  // Clone + inject ids for the inserted element subtree.
98
97
  let toInsert;
99
- if (parsedArgs.data.elements) {
100
- try {
101
- toInsert = reconstructTree(parsedArgs.data.elements);
102
- }
103
- catch (err) {
104
- return {
105
- success: false,
106
- error: err instanceof Error ? err.message : String(err),
107
- };
108
- }
109
- }
110
- else if (parsedArgs.data.element) {
111
- toInsert = [
112
- JSON.parse(JSON.stringify(parsedArgs.data.element ?? null)),
113
- ];
98
+ try {
99
+ toInsert = reconstructTree(parsedArgs.data.elements);
114
100
  }
115
- else {
101
+ catch (err) {
116
102
  return {
117
103
  success: false,
118
- error: "invalid elements format: neither element nor elements provided",
104
+ error: err instanceof Error ? err.message : String(err),
119
105
  };
120
106
  }
121
107
  for (const el of toInsert) {
@@ -1 +1 @@
1
- {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n resolvePageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nfunction reconstructTree(flatElements: any[]): BuilderElement[] {\n const rootFlats = flatElements.filter((el) => el.parentId === \"parent\");\n if (rootFlats.length === 0) {\n throw new Error(\"No root element found with parentId 'parent'\");\n }\n\n const buildMap = new Map<string, any>();\n for (const flat of flatElements) {\n buildMap.set(flat.id, {\n type: flat.type,\n className: flat.className,\n visible: flat.visible,\n props: flat.props ? JSON.parse(JSON.stringify(flat.props)) : undefined,\n children: [],\n });\n }\n\n for (const flat of flatElements) {\n if (flat.parentId === \"parent\") {\n continue;\n }\n const parentNode = buildMap.get(flat.parentId);\n if (!parentNode) {\n throw new Error(\n `Parent element with id '${flat.parentId}' not found in the list`,\n );\n }\n const currentNode = buildMap.get(flat.id);\n if (currentNode) {\n if (!parentNode.children) {\n parentNode.children = [];\n }\n parentNode.children.push(currentNode);\n }\n }\n\n return rootFlats.map((rootFlat) => buildMap.get(rootFlat.id));\n}\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n element?: BuilderElement | any[],\n beforeId?: string,\n ) => {\n const rawArgs =\n typeof routeOrArgs === \"object\" && routeOrArgs !== null\n ? (routeOrArgs as Record<string, unknown>)\n : {\n route: routeOrArgs,\n parent_id: parentId,\n before_id: beforeId,\n element: !Array.isArray(element) ? element : undefined,\n elements: Array.isArray(element) ? element : undefined,\n };\n\n const parsedArgs = InsertElementArgsZod.safeParse(rawArgs);\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parsedArgs.data.parent_id ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n const before_id = String(parsedArgs.data.before_id ?? \"\").trim();\n\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, parsedArgs.data.route, fs);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n let toInsert: BuilderElement[];\n if (parsedArgs.data.elements) {\n try {\n toInsert = reconstructTree(parsedArgs.data.elements);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n } else if (parsedArgs.data.element) {\n toInsert = [\n JSON.parse(JSON.stringify(parsedArgs.data.element ?? null)) as BuilderElement,\n ];\n } else {\n return {\n success: false,\n error: \"invalid elements format: neither element nor elements provided\",\n };\n }\n\n for (const el of toInsert) {\n await resolveUnsplashImagesDeep(el);\n }\n ensureElementIds(toInsert, existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\n const children = anyParent.children as BuilderElement[];\n if (before_id) {\n const idx = children.findIndex((c: any) => String(c?.id ?? \"\") === before_id);\n if (idx >= 0) {\n children.splice(idx, 0, ...toInsert);\n } else {\n children.push(...toInsert);\n }\n } else {\n children.push(...toInsert);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert[0] as any).id,\n inserted_ids: toInsert.map((el: any) => el.id),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
1
+ {"version":3,"file":"insertElement.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/insertElement.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveUnsplashImagesDeep } from \"../../../image/unsplash.service.js\";\nimport type { BuilderElement } from \"../../../types/elements.js\";\nimport {\n ensureElementIds,\n extractAllIdsDeep,\n findElementById,\n resolvePageConfigJsonPath,\n parsePageConfigJson,\n stringifyPageConfigJson,\n writeFileAtomic,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { InsertElementArgsZod } from \"../validators/builderElement.zod.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nfunction reconstructTree(flatElements: any[]): BuilderElement[] {\n const rootFlats = flatElements.filter((el) => el.parentId === \"parent\");\n if (rootFlats.length === 0) {\n throw new Error(\"No root element found with parentId 'parent'\");\n }\n\n const buildMap = new Map<string, any>();\n for (const flat of flatElements) {\n buildMap.set(flat.id, {\n type: flat.type,\n className: flat.className,\n visible: flat.visible,\n props: flat.props ? JSON.parse(JSON.stringify(flat.props)) : undefined,\n children: [],\n });\n }\n\n for (const flat of flatElements) {\n if (flat.parentId === \"parent\") {\n continue;\n }\n const parentNode = buildMap.get(flat.parentId);\n if (!parentNode) {\n throw new Error(\n `Parent element with id '${flat.parentId}' not found in the list`,\n );\n }\n const currentNode = buildMap.get(flat.id);\n if (currentNode) {\n if (!parentNode.children) {\n parentNode.children = [];\n }\n parentNode.children.push(currentNode);\n }\n }\n\n return rootFlats.map((rootFlat) => buildMap.get(rootFlat.id));\n}\n\nexport const createInsertElementImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (\n routeOrArgs: string | Record<string, unknown>,\n parentId?: string,\n inputElements?: any[],\n beforeId?: string,\n ) => {\n const rawArgs =\n typeof routeOrArgs === \"object\" && routeOrArgs !== null\n ? (routeOrArgs as Record<string, unknown>)\n : {\n route: routeOrArgs,\n parent_id: parentId,\n before_id: beforeId,\n elements: inputElements,\n };\n\n const parsedArgs = InsertElementArgsZod.safeParse(rawArgs);\n if (!parsedArgs.success) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: parsedArgs.error.flatten(),\n };\n }\n\n const parent_id = String(parsedArgs.data.parent_id ?? \"\").trim();\n if (!parent_id) return { success: false, error: \"invalid parent_id\" };\n\n const before_id = String(parsedArgs.data.before_id ?? \"\").trim();\n\n let configPath: string;\n try {\n configPath = await resolvePageConfigJsonPath(workspaceRoot, parsedArgs.data.route, fs);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let before = \"\";\n try {\n before = await fs.readFile(configPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return { success: false, error: \"not found\" };\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n let parsed: ReturnType<typeof parsePageConfigJson>;\n try {\n parsed = parsePageConfigJson(before);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const elements = parsed.elements ?? [];\n const existingIds = extractAllIdsDeep(elements);\n ensureElementIds(elements, existingIds);\n\n // Clone + inject ids for the inserted element subtree.\n let toInsert: BuilderElement[];\n try {\n toInsert = reconstructTree(parsedArgs.data.elements);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n for (const el of toInsert) {\n await resolveUnsplashImagesDeep(el);\n }\n ensureElementIds(toInsert, existingIds);\n\n const parent = findElementById(elements, parent_id);\n if (!parent) return { success: false, error: \"parent not found\" };\n\n const anyParent = parent as any;\n if (!anyParent.children || !Array.isArray(anyParent.children))\n anyParent.children = [];\n\n const children = anyParent.children as BuilderElement[];\n if (before_id) {\n const idx = children.findIndex((c: any) => String(c?.id ?? \"\") === before_id);\n if (idx >= 0) {\n children.splice(idx, 0, ...toInsert);\n } else {\n children.push(...toInsert);\n }\n } else {\n children.push(...toInsert);\n }\n\n const after = stringifyPageConfigJson({ elements });\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n inserted_id: (toInsert[0] as any).id,\n inserted_ids: toInsert.map((el: any) => el.id),\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n"]}
@@ -13,7 +13,6 @@ export declare const OnClickActionZod: z.ZodDiscriminatedUnion<[z.ZodObject<{
13
13
  href: z.ZodString;
14
14
  newTab: z.ZodOptional<z.ZodBoolean>;
15
15
  }, z.core.$strip>], "kind">;
16
- export declare const BuilderElementZod: z.ZodType<any>;
17
16
  export declare const FlatBuilderElementZod: z.ZodObject<{
18
17
  id: z.ZodString;
19
18
  parentId: z.ZodString;
@@ -62,8 +61,7 @@ export declare const InsertElementArgsZod: z.ZodObject<{
62
61
  route: z.ZodPipe<z.ZodTransform<string, unknown>, z.ZodString>;
63
62
  parent_id: z.ZodString;
64
63
  before_id: z.ZodOptional<z.ZodString>;
65
- element: z.ZodOptional<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>;
66
- elements: z.ZodOptional<z.ZodArray<z.ZodObject<{
64
+ elements: z.ZodArray<z.ZodObject<{
67
65
  id: z.ZodString;
68
66
  parentId: z.ZodString;
69
67
  type: z.ZodEnum<{
@@ -106,6 +104,6 @@ export declare const InsertElementArgsZod: z.ZodObject<{
106
104
  color: z.ZodOptional<z.ZodString>;
107
105
  strokeWidth: z.ZodOptional<z.ZodNumber>;
108
106
  }, z.core.$loose>>;
109
- }, z.core.$strip>>>;
107
+ }, z.core.$strip>>;
110
108
  }, z.core.$strip>;
111
109
  //# sourceMappingURL=builderElement.zod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builderElement.zod.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,8FAUhB,CAAC;AAoBX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;2BAsB3B,CAAC;AAoBH,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAM3C,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOhC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuB9B,CAAC"}
1
+ {"version":3,"file":"builderElement.zod.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,8FAUhB,CAAC;AAoBX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;2BAsB3B,CAAC;AAoBH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOhC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAc/B,CAAC"}
@@ -67,13 +67,6 @@ const BuilderElementPropsZod = z
67
67
  strokeWidth: z.number().optional(),
68
68
  })
69
69
  .passthrough();
70
- export const BuilderElementZod = z.object({
71
- type: z.enum(ELEMENT_TYPES),
72
- className: z.string().optional(),
73
- visible: z.boolean().optional(),
74
- props: BuilderElementPropsZod.optional(),
75
- children: z.array(z.lazy(() => BuilderElementZod)).optional(),
76
- });
77
70
  export const FlatBuilderElementZod = z.object({
78
71
  id: z.string().min(1),
79
72
  parentId: z.string().min(1),
@@ -82,8 +75,7 @@ export const FlatBuilderElementZod = z.object({
82
75
  visible: z.boolean().optional(),
83
76
  props: BuilderElementPropsZod.optional(),
84
77
  });
85
- export const InsertElementArgsZod = z
86
- .object({
78
+ export const InsertElementArgsZod = z.object({
87
79
  route: z.preprocess(normalizeInternalRoutePath, z
88
80
  .string()
89
81
  .min(1)
@@ -92,11 +84,6 @@ export const InsertElementArgsZod = z
92
84
  })),
93
85
  parent_id: z.string().min(1),
94
86
  before_id: z.string().min(1).optional(),
95
- element: BuilderElementZod.optional(),
96
- elements: z.array(FlatBuilderElementZod).min(1).optional(),
97
- })
98
- .refine((data) => data.element !== undefined || data.elements !== undefined, {
99
- message: "Either 'element' or 'elements' must be provided",
100
- path: ["element"],
87
+ elements: z.array(FlatBuilderElementZod).min(1),
101
88
  });
102
89
  //# sourceMappingURL=builderElement.zod.js.map
@@ -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\" 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\nconst BuilderElementPropsZod = 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\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: BuilderElementPropsZod.optional(),\n children: z.array(z.lazy(() => BuilderElementZod)).optional(),\n});\n\nexport const FlatBuilderElementZod = z.object({\n id: z.string().min(1),\n parentId: z.string().min(1),\n type: z.enum(ELEMENT_TYPES),\n className: z.string().optional(),\n visible: z.boolean().optional(),\n props: BuilderElementPropsZod.optional(),\n});\n\nexport const InsertElementArgsZod = z\n .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.optional(),\n elements: z.array(FlatBuilderElementZod).min(1).optional(),\n })\n .refine(\n (data) => data.element !== undefined || data.elements !== undefined,\n {\n message: \"Either 'element' or 'elements' must be provided\",\n path: [\"element\"],\n },\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\nconst BuilderElementPropsZod = 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\nexport const FlatBuilderElementZod = z.object({\n id: z.string().min(1),\n parentId: z.string().min(1),\n type: z.enum(ELEMENT_TYPES),\n className: z.string().optional(),\n visible: z.boolean().optional(),\n props: BuilderElementPropsZod.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 elements: z.array(FlatBuilderElementZod).min(1),\n});\n"]}
package/dist/core.d.ts CHANGED
@@ -32,11 +32,13 @@ export declare class QwintlyCore {
32
32
  readonly workspacePath: string;
33
33
  readonly source: string;
34
34
  readonly step: GenStep;
35
+ readonly geminiModel: string;
35
36
  private readonly aiClient?;
36
37
  private readonly statusRepo;
37
38
  private readonly ctxRepo;
38
39
  private readonly redisStatusPublisher;
39
40
  private readonly projectOpsRepo;
41
+ private readonly genTokensRepo;
40
42
  constructor(options: QwintlyCoreOptions);
41
43
  runAiFlow(initialContents: any[], tools: Tool[], maxSteps: number, terminalToolNames: string[], persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>): Promise<ToolLoopResult>;
42
44
  streamLog(message: string, eventType: EventType, displayedSummary?: boolean): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAGL,cAAc,EACf,MAAM,iCAAiC,CAAC;AAazC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAiBF,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,OAAO,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoB;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;gBAE1C,OAAO,EAAE,kBAAkB;IA2D1B,SAAS,CACpB,eAAe,EAAE,GAAG,EAAE,EACtB,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GACrE,OAAO,CAAC,cAAc,CAAC;IAyBb,SAAS,CACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,IAAI,CAAC;IA2BH,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC;YAQ1C,UAAU;IAMX,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;IAI5C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAY7E"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAGL,cAAc,EACf,MAAM,iCAAiC,CAAC;AAczC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAIhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAiBF,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,OAAO,CAAC;IAC9B,SAAgB,WAAW,EAAE,MAAM,CAAC;IAEpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoB;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;gBAExC,OAAO,EAAE,kBAAkB;IAiE1B,SAAS,CACpB,eAAe,EAAE,GAAG,EAAE,EACtB,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GACrE,OAAO,CAAC,cAAc,CAAC;IA8Bb,SAAS,CACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,IAAI,CAAC;IA2BH,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC;YAQ1C,UAAU;IAMX,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;IAI5C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAY7E"}
package/dist/core.js CHANGED
@@ -9,10 +9,12 @@ import { statusService } from "./logging/genStatus.service.js";
9
9
  import { SendStatusToRedis } from "./logging/redis.service.js";
10
10
  import { ContextRepository } from "./repository/context.repository.js";
11
11
  import { GenStatusRepository } from "./repository/genStatus.repository.js";
12
+ import { GenTokensRepository } from "./repository/genTokens.repository.js";
12
13
  import { ProjectOpsRepository } from "./repository/projectOperations.repository.js";
13
14
  import { applyOperations } from "./services/syncEditOps.service.js";
14
15
  import { initializeToolCallsRepository } from "./services/toolcallPersist.service.js";
15
16
  import { assertNonEmptyString } from "./utils/utils.js";
17
+ import { DEFAULT_MODEL } from "./ai/generate/gemini.client.js";
16
18
  export class QwintlyCore {
17
19
  constructor(options) {
18
20
  assertNonEmptyString(options.chatId, "chatId");
@@ -38,9 +40,11 @@ export class QwintlyCore {
38
40
  if (options.gemini?.apiKey) {
39
41
  this.aiClient = getClient("gemini", options.gemini.apiKey, options.gemini.model);
40
42
  }
43
+ this.geminiModel = options.gemini?.model ?? DEFAULT_MODEL;
41
44
  this.statusRepo = new GenStatusRepository(options.supabase.endpoint, options.supabase.secret);
42
45
  this.ctxRepo = new ContextRepository(options.supabase.endpoint, options.supabase.secret);
43
46
  this.projectOpsRepo = new ProjectOpsRepository(options.supabase.endpoint, options.supabase.secret);
47
+ this.genTokensRepo = new GenTokensRepository(options.supabase.endpoint, options.supabase.secret);
44
48
  this.redisStatusPublisher = new SendStatusToRedis(options.upstash.url, options.upstash.token);
45
49
  initializeToolCallsRepository(options.supabase.endpoint, options.supabase.secret, options.sessionId);
46
50
  console.log(`QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`);
@@ -61,6 +65,11 @@ export class QwintlyCore {
61
65
  }),
62
66
  logger: this.streamLog.bind(this),
63
67
  persistResponse,
68
+ tokenPersistence: {
69
+ repository: this.genTokensRepo,
70
+ sessionId: this.sessionId,
71
+ model: this.geminiModel,
72
+ },
64
73
  };
65
74
  const result = await runToolLoop(toolLoopOptions);
66
75
  return result;
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport { getClient } from \"./ai/generate/generateClient.js\";\nimport {\n runToolLoop,\n RunToolLoopOptions,\n ToolLoopResult,\n} from \"./ai/toolLoop/toolLoopRunner.js\";\nimport { initUnsplash } from \"./image/unsplash.service.js\";\nimport { buildCodegenIndex } from \"./indexer/codegenIndex.js\";\nimport { buildPlannerIndex } from \"./indexer/plannerIndex.js\";\nimport { computeProjectInfo } from \"./indexer/projectInfoIndex.js\";\nimport { buildValidatorIndex } from \"./indexer/validatorIndex.js\";\nimport { statusService } from \"./logging/genStatus.service.js\";\nimport { SendStatusToRedis } from \"./logging/redis.service.js\";\nimport { ContextRepository } from \"./repository/context.repository.js\";\nimport { GenStatusRepository } from \"./repository/genStatus.repository.js\";\nimport { ProjectOpsRepository } from \"./repository/projectOperations.repository.js\";\nimport { applyOperations } from \"./services/syncEditOps.service.js\";\nimport { initializeToolCallsRepository } from \"./services/toolcallPersist.service.js\";\nimport { EventType, GenStep } from \"./types/events.js\";\nimport {\n CodegenIndex,\n PlannerIndex,\n ValidatorIndex,\n} from \"./types/index/index.types.js\";\nimport type { ProjectInfo } from \"./types/projectInfo.types.js\";\nimport { assertNonEmptyString } from \"./utils/utils.js\";\n\nexport type QwintlyCoreOptions = {\n chatId: string;\n sessionId: string;\n workspacePath: string;\n source: string;\n step: GenStep;\n supabase: { endpoint: string; secret: string };\n upstash: { url: string; token: string };\n unsplash: { url: string; accessKey: string };\n gemini?: { apiKey: string; model?: string };\n};\n\ntype AiResponseOptions = {\n tools?: Tool[];\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\ntype AiClient = {\n aiResponse: (\n request: unknown,\n options?: AiResponseOptions,\n ) => Promise<{\n functionCalls?: any[];\n text?: string;\n }>;\n};\n\nexport class QwintlyCore {\n public readonly chatId: string;\n public readonly sessionId: string;\n public readonly workspacePath: string;\n public readonly source: string;\n public readonly step: GenStep;\n\n private readonly aiClient?: AiClient;\n private readonly statusRepo: GenStatusRepository;\n private readonly ctxRepo: ContextRepository;\n private readonly redisStatusPublisher: SendStatusToRedis;\n private readonly projectOpsRepo: ProjectOpsRepository;\n\n constructor(options: QwintlyCoreOptions) {\n assertNonEmptyString(options.chatId, \"chatId\");\n assertNonEmptyString(options.sessionId, \"sessionId\");\n assertNonEmptyString(options.workspacePath, \"workspacePath\");\n assertNonEmptyString(options.source, \"source\");\n assertNonEmptyString(options.step, \"step\");\n assertNonEmptyString(options.supabase?.endpoint, \"supabase.endpoint\");\n assertNonEmptyString(options.supabase?.secret, \"supabase.secret\");\n assertNonEmptyString(options.upstash?.url, \"upstash.url\");\n assertNonEmptyString(options.upstash?.token, \"upstash.token\");\n\n this.chatId = options.chatId;\n this.sessionId = options.sessionId;\n this.workspacePath = options.workspacePath;\n this.source = options.source;\n this.step = options.step;\n\n if (options.unsplash?.url && options.unsplash?.accessKey) {\n initUnsplash({\n url: options.unsplash.url,\n accessKey: options.unsplash.accessKey,\n });\n }\n\n if (options.gemini?.apiKey) {\n this.aiClient = getClient(\n \"gemini\",\n options.gemini.apiKey,\n options.gemini.model,\n ) as AiClient;\n }\n\n this.statusRepo = new GenStatusRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.ctxRepo = new ContextRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.projectOpsRepo = new ProjectOpsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.redisStatusPublisher = new SendStatusToRedis(\n options.upstash.url,\n options.upstash.token,\n );\n initializeToolCallsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n options.sessionId,\n );\n\n console.log(\n `QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`,\n );\n }\n\n public async runAiFlow(\n initialContents: any[],\n tools: Tool[],\n maxSteps: number,\n terminalToolNames: string[],\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>,\n ): Promise<ToolLoopResult> {\n if (!this.aiClient) {\n throw new Error(\n \"AI client not initialized. Please provide 'gemini' config to use runAiFlow.\",\n );\n }\n const toolLoopOptions: RunToolLoopOptions = {\n initialContents: initialContents,\n tools: tools,\n workspaceRoot: this.workspacePath,\n maxSteps: maxSteps,\n terminalToolNames: terminalToolNames,\n aiCall: (request, options) =>\n this.aiClient!.aiResponse(request, {\n tools: options.tools,\n toolCallingMode: options.toolCallingMode,\n }),\n logger: this.streamLog.bind(this),\n persistResponse,\n };\n\n const result = await runToolLoop(toolLoopOptions);\n return result;\n }\n\n public async streamLog(\n message: string,\n eventType: EventType,\n displayedSummary: boolean = false,\n ): Promise<void> {\n try {\n assertNonEmptyString(message, \"message\");\n await statusService(\n this.chatId,\n this.sessionId,\n eventType,\n this.step,\n message,\n this.source,\n {\n repository: {\n persist: this.statusRepo.persistStatusMessage.bind(this.statusRepo),\n },\n publisher: {\n publish: this.redisStatusPublisher.sendStatusToRedis.bind(\n this.redisStatusPublisher,\n ),\n },\n },\n displayedSummary,\n );\n } catch (error) {\n console.error(error);\n }\n }\n\n public async buildProjectInfoIdx(): Promise<ProjectInfo> {\n const projectInfo = await computeProjectInfo(this.workspacePath);\n\n await this.ctxRepo.updateProjectInfo(this.chatId, projectInfo);\n\n return projectInfo;\n }\n\n private async buildIndex<T>(\n builder: (path: string) => Promise<T>,\n ): Promise<T> {\n return builder(this.workspacePath);\n }\n\n public async buildPlannerIdx(): Promise<PlannerIndex> {\n return this.buildIndex(buildPlannerIndex);\n }\n\n public async buildCodegenIdx(): Promise<CodegenIndex> {\n return this.buildIndex(buildCodegenIndex);\n }\n\n public async buildValidatorIdx(): Promise<ValidatorIndex> {\n return this.buildIndex(buildValidatorIndex);\n }\n\n public async syncEditOps(genId: string, workspace: string): Promise<boolean> {\n if (!genId) return false;\n const projectOpsRepo = this.projectOpsRepo;\n const ops = await projectOpsRepo.fetchProjectOperations(genId);\n if (!ops || ops.length === 0) return false;\n const appliedIds = await applyOperations(ops, workspace);\n if (appliedIds.length > 0) {\n await projectOpsRepo.markOperationsApplied(appliedIds);\n }\n const isModified = appliedIds.length > 0;\n return isModified;\n }\n}\n"]}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport { getClient } from \"./ai/generate/generateClient.js\";\nimport {\n runToolLoop,\n RunToolLoopOptions,\n ToolLoopResult,\n} from \"./ai/toolLoop/toolLoopRunner.js\";\nimport { initUnsplash } from \"./image/unsplash.service.js\";\nimport { buildCodegenIndex } from \"./indexer/codegenIndex.js\";\nimport { buildPlannerIndex } from \"./indexer/plannerIndex.js\";\nimport { computeProjectInfo } from \"./indexer/projectInfoIndex.js\";\nimport { buildValidatorIndex } from \"./indexer/validatorIndex.js\";\nimport { statusService } from \"./logging/genStatus.service.js\";\nimport { SendStatusToRedis } from \"./logging/redis.service.js\";\nimport { ContextRepository } from \"./repository/context.repository.js\";\nimport { GenStatusRepository } from \"./repository/genStatus.repository.js\";\nimport { GenTokensRepository } from \"./repository/genTokens.repository.js\";\nimport { ProjectOpsRepository } from \"./repository/projectOperations.repository.js\";\nimport { applyOperations } from \"./services/syncEditOps.service.js\";\nimport { initializeToolCallsRepository } from \"./services/toolcallPersist.service.js\";\nimport { EventType, GenStep } from \"./types/events.js\";\nimport {\n CodegenIndex,\n PlannerIndex,\n ValidatorIndex,\n} from \"./types/index/index.types.js\";\nimport type { ProjectInfo } from \"./types/projectInfo.types.js\";\nimport { assertNonEmptyString } from \"./utils/utils.js\";\nimport { DEFAULT_MODEL } from \"./ai/generate/gemini.client.js\";\n\nexport type QwintlyCoreOptions = {\n chatId: string;\n sessionId: string;\n workspacePath: string;\n source: string;\n step: GenStep;\n supabase: { endpoint: string; secret: string };\n upstash: { url: string; token: string };\n unsplash: { url: string; accessKey: string };\n gemini?: { apiKey: string; model?: string };\n};\n\ntype AiResponseOptions = {\n tools?: Tool[];\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\ntype AiClient = {\n aiResponse: (\n request: unknown,\n options?: AiResponseOptions,\n ) => Promise<{\n functionCalls?: any[];\n text?: string;\n }>;\n};\n\nexport class QwintlyCore {\n public readonly chatId: string;\n public readonly sessionId: string;\n public readonly workspacePath: string;\n public readonly source: string;\n public readonly step: GenStep;\n public readonly geminiModel: string;\n\n private readonly aiClient?: AiClient;\n private readonly statusRepo: GenStatusRepository;\n private readonly ctxRepo: ContextRepository;\n private readonly redisStatusPublisher: SendStatusToRedis;\n private readonly projectOpsRepo: ProjectOpsRepository;\n private readonly genTokensRepo: GenTokensRepository;\n\n constructor(options: QwintlyCoreOptions) {\n assertNonEmptyString(options.chatId, \"chatId\");\n assertNonEmptyString(options.sessionId, \"sessionId\");\n assertNonEmptyString(options.workspacePath, \"workspacePath\");\n assertNonEmptyString(options.source, \"source\");\n assertNonEmptyString(options.step, \"step\");\n assertNonEmptyString(options.supabase?.endpoint, \"supabase.endpoint\");\n assertNonEmptyString(options.supabase?.secret, \"supabase.secret\");\n assertNonEmptyString(options.upstash?.url, \"upstash.url\");\n assertNonEmptyString(options.upstash?.token, \"upstash.token\");\n\n this.chatId = options.chatId;\n this.sessionId = options.sessionId;\n this.workspacePath = options.workspacePath;\n this.source = options.source;\n this.step = options.step;\n\n if (options.unsplash?.url && options.unsplash?.accessKey) {\n initUnsplash({\n url: options.unsplash.url,\n accessKey: options.unsplash.accessKey,\n });\n }\n\n if (options.gemini?.apiKey) {\n this.aiClient = getClient(\n \"gemini\",\n options.gemini.apiKey,\n options.gemini.model,\n ) as AiClient;\n }\n\n this.geminiModel = options.gemini?.model ?? DEFAULT_MODEL;\n\n this.statusRepo = new GenStatusRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.ctxRepo = new ContextRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.projectOpsRepo = new ProjectOpsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.genTokensRepo = new GenTokensRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.redisStatusPublisher = new SendStatusToRedis(\n options.upstash.url,\n options.upstash.token,\n );\n initializeToolCallsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n options.sessionId,\n );\n\n console.log(\n `QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`,\n );\n }\n\n public async runAiFlow(\n initialContents: any[],\n tools: Tool[],\n maxSteps: number,\n terminalToolNames: string[],\n persistResponse?: (modelInput: any, modelOutput: any) => Promise<void>,\n ): Promise<ToolLoopResult> {\n if (!this.aiClient) {\n throw new Error(\n \"AI client not initialized. Please provide 'gemini' config to use runAiFlow.\",\n );\n }\n const toolLoopOptions: RunToolLoopOptions = {\n initialContents: initialContents,\n tools: tools,\n workspaceRoot: this.workspacePath,\n maxSteps: maxSteps,\n terminalToolNames: terminalToolNames,\n aiCall: (request, options) =>\n this.aiClient!.aiResponse(request, {\n tools: options.tools,\n toolCallingMode: options.toolCallingMode,\n }),\n logger: this.streamLog.bind(this),\n persistResponse,\n tokenPersistence: {\n repository: this.genTokensRepo,\n sessionId: this.sessionId,\n model: this.geminiModel,\n },\n };\n\n const result = await runToolLoop(toolLoopOptions);\n return result;\n }\n\n public async streamLog(\n message: string,\n eventType: EventType,\n displayedSummary: boolean = false,\n ): Promise<void> {\n try {\n assertNonEmptyString(message, \"message\");\n await statusService(\n this.chatId,\n this.sessionId,\n eventType,\n this.step,\n message,\n this.source,\n {\n repository: {\n persist: this.statusRepo.persistStatusMessage.bind(this.statusRepo),\n },\n publisher: {\n publish: this.redisStatusPublisher.sendStatusToRedis.bind(\n this.redisStatusPublisher,\n ),\n },\n },\n displayedSummary,\n );\n } catch (error) {\n console.error(error);\n }\n }\n\n public async buildProjectInfoIdx(): Promise<ProjectInfo> {\n const projectInfo = await computeProjectInfo(this.workspacePath);\n\n await this.ctxRepo.updateProjectInfo(this.chatId, projectInfo);\n\n return projectInfo;\n }\n\n private async buildIndex<T>(\n builder: (path: string) => Promise<T>,\n ): Promise<T> {\n return builder(this.workspacePath);\n }\n\n public async buildPlannerIdx(): Promise<PlannerIndex> {\n return this.buildIndex(buildPlannerIndex);\n }\n\n public async buildCodegenIdx(): Promise<CodegenIndex> {\n return this.buildIndex(buildCodegenIndex);\n }\n\n public async buildValidatorIdx(): Promise<ValidatorIndex> {\n return this.buildIndex(buildValidatorIndex);\n }\n\n public async syncEditOps(genId: string, workspace: string): Promise<boolean> {\n if (!genId) return false;\n const projectOpsRepo = this.projectOpsRepo;\n const ops = await projectOpsRepo.fetchProjectOperations(genId);\n if (!ops || ops.length === 0) return false;\n const appliedIds = await applyOperations(ops, workspace);\n if (appliedIds.length > 0) {\n await projectOpsRepo.markOperationsApplied(appliedIds);\n }\n const isModified = appliedIds.length > 0;\n return isModified;\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { DBRepository } from "./repository.js";
2
+ export declare class GenTokensRepository extends DBRepository {
3
+ persistGenTokens(sessionId: string, input_tokens: number, output_tokens: number, model: string): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=genTokens.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genTokens.repository.d.ts","sourceRoot":"","sources":["../../src/repository/genTokens.repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,qBAAa,mBAAoB,SAAQ,YAAY;IACtC,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC;CAYjB"}
@@ -0,0 +1,15 @@
1
+ import { DBRepository } from "./repository.js";
2
+ export class GenTokensRepository extends DBRepository {
3
+ async persistGenTokens(sessionId, input_tokens, output_tokens, model) {
4
+ const { error } = await this.client.rpc("persist_gen_tokens", {
5
+ p_gen_id: sessionId,
6
+ p_input_tokens: input_tokens,
7
+ p_output_tokens: output_tokens,
8
+ model: model,
9
+ });
10
+ if (error) {
11
+ console.error(`Failed calling persist_gen_tokens RPC: ${error.message}`);
12
+ }
13
+ }
14
+ }
15
+ //# sourceMappingURL=genTokens.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genTokens.repository.js","sourceRoot":"","sources":["../../src/repository/genTokens.repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IAC5C,KAAK,CAAC,gBAAgB,CAC3B,SAAiB,EACjB,YAAoB,EACpB,aAAqB,EACrB,KAAa;QAEb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE;YAC5D,QAAQ,EAAE,SAAS;YACnB,cAAc,EAAE,YAAY;YAC5B,eAAe,EAAE,aAAa;YAC9B,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QAEH,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,0CAA0C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;CACF","sourcesContent":["import { DBRepository } from \"./repository.js\";\r\n\r\nexport class GenTokensRepository extends DBRepository {\r\n public async persistGenTokens(\r\n sessionId: string,\r\n input_tokens: number,\r\n output_tokens: number,\r\n model: string,\r\n ): Promise<void> {\r\n const { error } = await this.client.rpc(\"persist_gen_tokens\", {\r\n p_gen_id: sessionId,\r\n p_input_tokens: input_tokens,\r\n p_output_tokens: output_tokens,\r\n model: model,\r\n });\r\n\r\n if (error) {\r\n console.error(`Failed calling persist_gen_tokens RPC: ${error.message}`);\r\n }\r\n }\r\n}\r\n"]}
@@ -40,10 +40,9 @@ test("insert/update tools: inject ids, insert under parent, update props and cla
40
40
  const insert = createInsertElementImpl(deps);
41
41
  const updateProps = createUpdatePropsImpl(deps);
42
42
  const updateClassName = createUpdateClassNameImpl(deps);
43
- const inserted = await insert("/a", "root", {
44
- type: "text",
45
- props: { text: "hello" },
46
- });
43
+ const inserted = await insert("/a", "root", [
44
+ { id: "new_el", parentId: "parent", type: "text", props: { text: "hello" } }
45
+ ]);
47
46
  assert.equal(inserted.success, true, `unexpected response: ${JSON.stringify(inserted)}`);
48
47
  const insertedId = inserted.inserted_id;
49
48
  assert.ok(typeof insertedId === "string" && insertedId.startsWith("el_"));
@@ -51,7 +50,9 @@ test("insert/update tools: inject ids, insert under parent, update props and cla
51
50
  route: "/a",
52
51
  parent_id: "root",
53
52
  before_id: "existing",
54
- element: { type: "text", props: { text: "first" } },
53
+ elements: [
54
+ { id: "first_el", parentId: "parent", type: "text", props: { text: "first" } }
55
+ ],
55
56
  });
56
57
  assert.equal(inserted2.success, true, `unexpected response: ${JSON.stringify(inserted2)}`);
57
58
  const inserted2Id = inserted2.inserted_id;
@@ -134,11 +135,9 @@ test("dynamic/nested routes resolution in tools", async () => {
134
135
  const updateProps = createUpdatePropsImpl(deps);
135
136
  const updateClassName = createUpdateClassNameImpl(deps);
136
137
  const deleteElement = createDeleteElementImpl(deps);
137
- // Test insert_element on dynamic route '/product/123'
138
- const insRes = await insert("/product/123", "root", {
139
- type: "button",
140
- props: { text: "Buy Now" },
141
- });
138
+ const insRes = await insert("/product/123", "root", [
139
+ { id: "buy_btn", parentId: "parent", type: "button", props: { text: "Buy Now" } }
140
+ ]);
142
141
  assert.equal(insRes.success, true);
143
142
  // Verify it updated '/app/product/[id]/pageConfig.json'
144
143
  const afterProduct = JSON.parse(await fs.readFile(filePath, "utf-8"));
@@ -1 +1 @@
1
- {"version":3,"file":"insertUpdate.impl.test.js","sourceRoot":"","sources":["../../src/tests/insertUpdate.impl.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs/promises\";\nimport { createInsertElementImpl } from \"../ai/tools/implementations/insertElement.impl.js\";\nimport { createUpdatePropsImpl } from \"../ai/tools/implementations/updateProps.impl.js\";\nimport { createUpdateClassNameImpl } from \"../ai/tools/implementations/updateClassName.impl.js\";\nimport { createDeleteElementImpl } from \"../ai/tools/implementations/deleteElement.impl.js\";\nimport { matchRoute } from \"../ai/tools/helpers/pageConfigJson.helpers.js\";\n\ntype Deps = Parameters<typeof createInsertElementImpl>[0];\ntype CoreFs = Deps[\"fs\"];\n\nconst makeRealFs = (overrides?: Partial<CoreFs>): CoreFs => {\n return {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n ...(overrides ?? {}),\n };\n};\n\ntest(\"insert/update tools: inject ids, insert under parent, update props and classname\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"a\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [{ id: \"existing\", type: \"text\", props: { text: \"x\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n const updateProps = createUpdatePropsImpl(deps);\n const updateClassName = createUpdateClassNameImpl(deps);\n\n const inserted = await insert(\"/a\", \"root\", {\n type: \"text\",\n props: { text: \"hello\" },\n } as any);\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n const insertedId = (inserted as any).inserted_id as string;\n assert.ok(typeof insertedId === \"string\" && insertedId.startsWith(\"el_\"));\n\n const inserted2 = await insert({\n route: \"/a\",\n parent_id: \"root\",\n before_id: \"existing\",\n element: { type: \"text\", props: { text: \"first\" } },\n } as any);\n assert.equal(\n (inserted2 as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted2)}`,\n );\n const inserted2Id = (inserted2 as any).inserted_id as string;\n assert.ok(typeof inserted2Id === \"string\" && inserted2Id.startsWith(\"el_\"));\n\n const up1 = await updateProps({\n route: \"/a\",\n element_id: insertedId,\n text: \"updated\",\n href: \"/x\",\n } as any);\n assert.equal((up1 as any).success, true);\n\n const up2 = await updateClassName(\"/a\", insertedId, \"text-red-500\");\n assert.equal((up2 as any).success, true);\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children[0].id, inserted2Id);\n assert.equal(children[1].id, \"existing\");\n\n const found = children.find((e) => e.id === insertedId);\n assert.ok(found);\n assert.equal(found.props.text, \"updated\");\n assert.equal(found.props.href, \"/x\");\n assert.equal(found.className, \"text-red-500\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"matchRoute helper correctly matches physical paths\", () => {\n // exact match\n assert.equal(matchRoute(\"/\", \"/\"), true);\n assert.equal(matchRoute(\"/dashboard\", \"/dashboard\"), true);\n assert.equal(matchRoute(\"/dashboard\", \"/dashboard/\"), true);\n assert.equal(matchRoute(\"/dashboard/\", \"/dashboard\"), true);\n \n // dynamic segment\n assert.equal(matchRoute(\"/product/[id]\", \"/product/123\"), true);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/hi\"), true);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/\"), false);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/123/reviews\"), false);\n assert.equal(matchRoute(\"/product/[id]/reviews\", \"/product/abc/reviews\"), true);\n\n // catch-all segment\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog/react\"), true);\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog/react/hooks/state\"), true);\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog\"), false); // required catch-all requires at least one segment\n\n // optional catch-all segment\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog\"), true);\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog/react\"), true);\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog/react/hooks\"), true);\n});\n\ntest(\"dynamic/nested routes resolution in tools\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-dynamic-\"));\n try {\n // 1. Create a dynamic route /product/[id]\n const routeDir = path.join(workspaceRoot, \"app\", \"product\", \"[id]\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [{ id: \"prod_title\", type: \"text\", props: { text: \"Product Name\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n // 2. Create a catch-all route /blog/[...slug]\n const blogDir = path.join(workspaceRoot, \"app\", \"blog\", \"[...slug]\");\n await fs.mkdir(blogDir, { recursive: true });\n const blogFilePath = path.join(blogDir, \"pageConfig.json\");\n await fs.writeFile(\n blogFilePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"blog_root\",\n type: \"div\",\n children: [{ id: \"blog_content\", type: \"text\", props: { text: \"Blog Post\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n const updateProps = createUpdatePropsImpl(deps);\n const updateClassName = createUpdateClassNameImpl(deps);\n const deleteElement = createDeleteElementImpl(deps);\n\n // Test insert_element on dynamic route '/product/123'\n const insRes = await insert(\"/product/123\", \"root\", {\n type: \"button\",\n props: { text: \"Buy Now\" },\n } as any);\n assert.equal(insRes.success, true);\n\n // Verify it updated '/app/product/[id]/pageConfig.json'\n const afterProduct = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n assert.equal(afterProduct.elements[0].children.length, 2);\n const newBtn = afterProduct.elements[0].children[1];\n assert.equal(newBtn.type, \"button\");\n assert.equal(newBtn.props.text, \"Buy Now\");\n\n // Test update_props on dynamic route '/product/hi-there'\n const upRes = await updateProps({\n route: \"/product/hi-there\",\n element_id: \"prod_title\",\n text: \"Updated Product Title\",\n } as any);\n assert.equal(upRes.success, true);\n\n // Test update_classname on catch-all route '/blog/react/hooks/state'\n const classRes = await updateClassName(\"/blog/react/hooks/state\", \"blog_content\", \"text-blue-500\");\n assert.equal(classRes.success, true);\n\n // Verify blog config updated\n const afterBlog = JSON.parse(await fs.readFile(blogFilePath, \"utf-8\"));\n const updatedTitle = afterBlog.elements[0].children[0];\n assert.equal(updatedTitle.className, \"text-blue-500\");\n\n // Test delete_element on catch-all route\n const delRes = await deleteElement(\"/blog/react/something-else\", \"blog_content\");\n assert.equal(delRes.success, true);\n\n const afterDelBlog = JSON.parse(await fs.readFile(blogFilePath, \"utf-8\"));\n assert.equal(afterDelBlog.elements[0].children.length, 0);\n\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"insert tool: supports flat elements list with parent-child mapping\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-flat-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"flat-test\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n\n // Call insert using the flat elements format\n const inserted = await insert({\n route: \"/flat-test\",\n parent_id: \"root\",\n elements: [\n {\n id: \"container\",\n parentId: \"parent\",\n type: \"div\",\n className: \"bg-red-500\",\n },\n {\n id: \"heading\",\n parentId: \"container\",\n type: \"text\",\n props: { text: \"Hello from Flat List\" },\n },\n ],\n } as any);\n\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children.length, 1);\n \n const insertedContainer = children[0];\n assert.equal(insertedContainer.className, \"bg-red-500\");\n assert.equal(insertedContainer.type, \"div\");\n \n // Verify children inside the container\n assert.equal(insertedContainer.children.length, 1);\n const insertedHeading = insertedContainer.children[0];\n assert.equal(insertedHeading.type, \"text\");\n assert.equal(insertedHeading.props.text, \"Hello from Flat List\");\n \n // Verify that proper real IDs starting with el_ were generated\n assert.ok(insertedContainer.id.startsWith(\"el_\"));\n assert.ok(insertedHeading.id.startsWith(\"el_\"));\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"insert tool: supports multiple sibling root elements in flat array\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-multi-flat-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"multi-flat-test\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n\n // Call insert with two sibling root elements\n const inserted = await insert({\n route: \"/multi-flat-test\",\n parent_id: \"root\",\n elements: [\n {\n id: \"card_1\",\n parentId: \"parent\",\n type: \"div\",\n className: \"card-1\",\n },\n {\n id: \"card_2\",\n parentId: \"parent\",\n type: \"div\",\n className: \"card-2\",\n },\n {\n id: \"heading_1\",\n parentId: \"card_1\",\n type: \"text\",\n props: { text: \"Heading 1\" },\n },\n ],\n } as any);\n\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n\n assert.ok(Array.isArray((inserted as any).inserted_ids));\n assert.equal((inserted as any).inserted_ids.length, 2);\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children.length, 2);\n\n assert.equal(children[0].className, \"card-1\");\n assert.equal(children[1].className, \"card-2\");\n\n assert.equal(children[0].children.length, 1);\n assert.equal(children[0].children[0].props.text, \"Heading 1\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n"]}
1
+ {"version":3,"file":"insertUpdate.impl.test.js","sourceRoot":"","sources":["../../src/tests/insertUpdate.impl.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs/promises\";\nimport { createInsertElementImpl } from \"../ai/tools/implementations/insertElement.impl.js\";\nimport { createUpdatePropsImpl } from \"../ai/tools/implementations/updateProps.impl.js\";\nimport { createUpdateClassNameImpl } from \"../ai/tools/implementations/updateClassName.impl.js\";\nimport { createDeleteElementImpl } from \"../ai/tools/implementations/deleteElement.impl.js\";\nimport { matchRoute } from \"../ai/tools/helpers/pageConfigJson.helpers.js\";\n\ntype Deps = Parameters<typeof createInsertElementImpl>[0];\ntype CoreFs = Deps[\"fs\"];\n\nconst makeRealFs = (overrides?: Partial<CoreFs>): CoreFs => {\n return {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n ...(overrides ?? {}),\n };\n};\n\ntest(\"insert/update tools: inject ids, insert under parent, update props and classname\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"a\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [{ id: \"existing\", type: \"text\", props: { text: \"x\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n const updateProps = createUpdatePropsImpl(deps);\n const updateClassName = createUpdateClassNameImpl(deps);\n\n const inserted = await insert(\"/a\", \"root\", [\n { id: \"new_el\", parentId: \"parent\", type: \"text\", props: { text: \"hello\" } }\n ] as any);\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n const insertedId = (inserted as any).inserted_id as string;\n assert.ok(typeof insertedId === \"string\" && insertedId.startsWith(\"el_\"));\n\n const inserted2 = await insert({\n route: \"/a\",\n parent_id: \"root\",\n before_id: \"existing\",\n elements: [\n { id: \"first_el\", parentId: \"parent\", type: \"text\", props: { text: \"first\" } }\n ],\n } as any);\n assert.equal(\n (inserted2 as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted2)}`,\n );\n const inserted2Id = (inserted2 as any).inserted_id as string;\n assert.ok(typeof inserted2Id === \"string\" && inserted2Id.startsWith(\"el_\"));\n\n const up1 = await updateProps({\n route: \"/a\",\n element_id: insertedId,\n text: \"updated\",\n href: \"/x\",\n } as any);\n assert.equal((up1 as any).success, true);\n\n const up2 = await updateClassName(\"/a\", insertedId, \"text-red-500\");\n assert.equal((up2 as any).success, true);\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children[0].id, inserted2Id);\n assert.equal(children[1].id, \"existing\");\n\n const found = children.find((e) => e.id === insertedId);\n assert.ok(found);\n assert.equal(found.props.text, \"updated\");\n assert.equal(found.props.href, \"/x\");\n assert.equal(found.className, \"text-red-500\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"matchRoute helper correctly matches physical paths\", () => {\n // exact match\n assert.equal(matchRoute(\"/\", \"/\"), true);\n assert.equal(matchRoute(\"/dashboard\", \"/dashboard\"), true);\n assert.equal(matchRoute(\"/dashboard\", \"/dashboard/\"), true);\n assert.equal(matchRoute(\"/dashboard/\", \"/dashboard\"), true);\n \n // dynamic segment\n assert.equal(matchRoute(\"/product/[id]\", \"/product/123\"), true);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/hi\"), true);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/\"), false);\n assert.equal(matchRoute(\"/product/[id]\", \"/product/123/reviews\"), false);\n assert.equal(matchRoute(\"/product/[id]/reviews\", \"/product/abc/reviews\"), true);\n\n // catch-all segment\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog/react\"), true);\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog/react/hooks/state\"), true);\n assert.equal(matchRoute(\"/blog/[...slug]\", \"/blog\"), false); // required catch-all requires at least one segment\n\n // optional catch-all segment\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog\"), true);\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog/react\"), true);\n assert.equal(matchRoute(\"/blog/[[...slug]]\", \"/blog/react/hooks\"), true);\n});\n\ntest(\"dynamic/nested routes resolution in tools\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-dynamic-\"));\n try {\n // 1. Create a dynamic route /product/[id]\n const routeDir = path.join(workspaceRoot, \"app\", \"product\", \"[id]\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [{ id: \"prod_title\", type: \"text\", props: { text: \"Product Name\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n // 2. Create a catch-all route /blog/[...slug]\n const blogDir = path.join(workspaceRoot, \"app\", \"blog\", \"[...slug]\");\n await fs.mkdir(blogDir, { recursive: true });\n const blogFilePath = path.join(blogDir, \"pageConfig.json\");\n await fs.writeFile(\n blogFilePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"blog_root\",\n type: \"div\",\n children: [{ id: \"blog_content\", type: \"text\", props: { text: \"Blog Post\" } }],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n const updateProps = createUpdatePropsImpl(deps);\n const updateClassName = createUpdateClassNameImpl(deps);\n const deleteElement = createDeleteElementImpl(deps);\n\n const insRes = await insert(\"/product/123\", \"root\", [\n { id: \"buy_btn\", parentId: \"parent\", type: \"button\", props: { text: \"Buy Now\" } }\n ] as any);\n assert.equal(insRes.success, true);\n\n // Verify it updated '/app/product/[id]/pageConfig.json'\n const afterProduct = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n assert.equal(afterProduct.elements[0].children.length, 2);\n const newBtn = afterProduct.elements[0].children[1];\n assert.equal(newBtn.type, \"button\");\n assert.equal(newBtn.props.text, \"Buy Now\");\n\n // Test update_props on dynamic route '/product/hi-there'\n const upRes = await updateProps({\n route: \"/product/hi-there\",\n element_id: \"prod_title\",\n text: \"Updated Product Title\",\n } as any);\n assert.equal(upRes.success, true);\n\n // Test update_classname on catch-all route '/blog/react/hooks/state'\n const classRes = await updateClassName(\"/blog/react/hooks/state\", \"blog_content\", \"text-blue-500\");\n assert.equal(classRes.success, true);\n\n // Verify blog config updated\n const afterBlog = JSON.parse(await fs.readFile(blogFilePath, \"utf-8\"));\n const updatedTitle = afterBlog.elements[0].children[0];\n assert.equal(updatedTitle.className, \"text-blue-500\");\n\n // Test delete_element on catch-all route\n const delRes = await deleteElement(\"/blog/react/something-else\", \"blog_content\");\n assert.equal(delRes.success, true);\n\n const afterDelBlog = JSON.parse(await fs.readFile(blogFilePath, \"utf-8\"));\n assert.equal(afterDelBlog.elements[0].children.length, 0);\n\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"insert tool: supports flat elements list with parent-child mapping\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-flat-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"flat-test\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n\n // Call insert using the flat elements format\n const inserted = await insert({\n route: \"/flat-test\",\n parent_id: \"root\",\n elements: [\n {\n id: \"container\",\n parentId: \"parent\",\n type: \"div\",\n className: \"bg-red-500\",\n },\n {\n id: \"heading\",\n parentId: \"container\",\n type: \"text\",\n props: { text: \"Hello from Flat List\" },\n },\n ],\n } as any);\n\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children.length, 1);\n \n const insertedContainer = children[0];\n assert.equal(insertedContainer.className, \"bg-red-500\");\n assert.equal(insertedContainer.type, \"div\");\n \n // Verify children inside the container\n assert.equal(insertedContainer.children.length, 1);\n const insertedHeading = insertedContainer.children[0];\n assert.equal(insertedHeading.type, \"text\");\n assert.equal(insertedHeading.props.text, \"Hello from Flat List\");\n \n // Verify that proper real IDs starting with el_ were generated\n assert.ok(insertedContainer.id.startsWith(\"el_\"));\n assert.ok(insertedHeading.id.startsWith(\"el_\"));\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"insert tool: supports multiple sibling root elements in flat array\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-multi-flat-\"));\n try {\n const routeDir = path.join(workspaceRoot, \"app\", \"multi-flat-test\");\n await fs.mkdir(routeDir, { recursive: true });\n const filePath = path.join(routeDir, \"pageConfig.json\");\n await fs.writeFile(\n filePath,\n JSON.stringify(\n {\n elements: [\n {\n id: \"root\",\n type: \"div\",\n children: [],\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const deps = { workspaceRoot, fs: makeRealFs() } as any;\n const insert = createInsertElementImpl(deps);\n\n // Call insert with two sibling root elements\n const inserted = await insert({\n route: \"/multi-flat-test\",\n parent_id: \"root\",\n elements: [\n {\n id: \"card_1\",\n parentId: \"parent\",\n type: \"div\",\n className: \"card-1\",\n },\n {\n id: \"card_2\",\n parentId: \"parent\",\n type: \"div\",\n className: \"card-2\",\n },\n {\n id: \"heading_1\",\n parentId: \"card_1\",\n type: \"text\",\n props: { text: \"Heading 1\" },\n },\n ],\n } as any);\n\n assert.equal(\n (inserted as any).success,\n true,\n `unexpected response: ${JSON.stringify(inserted)}`,\n );\n\n assert.ok(Array.isArray((inserted as any).inserted_ids));\n assert.equal((inserted as any).inserted_ids.length, 2);\n\n const after = JSON.parse(await fs.readFile(filePath, \"utf-8\"));\n const children = after.elements[0].children as any[];\n assert.equal(children.length, 2);\n\n assert.equal(children[0].className, \"card-1\");\n assert.equal(children[1].className, \"card-2\");\n\n assert.equal(children[0].children.length, 1);\n assert.equal(children[0].children[0].props.text, \"Heading 1\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n"]}
@@ -23,7 +23,9 @@ test("tool loop: insert_element failure includes available routes and hint", asy
23
23
  args: {
24
24
  route: "/invalid-route",
25
25
  parent_id: "root",
26
- element: { type: "text", props: { text: "hi" } },
26
+ elements: [
27
+ { id: "text_el", parentId: "parent", type: "text", props: { text: "hi" } }
28
+ ],
27
29
  },
28
30
  },
29
31
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"toolLoopRunner.routes.test.js","sourceRoot":"","sources":["../../src/tests/toolLoopRunner.routes.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACtF,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,iCAAiC;QACjC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1F,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,aAAa,EAAE;wBACb;4BACE,IAAI,EAAE,gBAAgB;4BACtB,IAAI,EAAE;gCACJ,KAAK,EAAE,gBAAgB;gCACvB,SAAS,EAAE,MAAM;gCACjB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;6BACjD;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;YAC5B,eAAe,EAAE,EAAE;YACnB,KAAK,EAAE,EAAE;YACT,aAAa;YACb,MAAM;YACN,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACtB,eAAe,EAAE,yBAAyB,CAAC,GAAG;YAC9C,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAC5C,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,EAAE,IAAI,KAAK,MAAM;YAClB,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;YACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,gBAAgB,CAAC,CAC3E,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC1C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,gBAAgB,CAC3D,EAAE,gBAAgB,EAAE,QAAQ,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,wBAAwB,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;IAClE,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7E,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1F,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;iBAC5D,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;YAC5B,eAAe,EAAE,EAAE;YACnB,KAAK,EAAE,EAAE;YACT,aAAa;YACb,MAAM;YACN,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACtB,eAAe,EAAE,yBAAyB,CAAC,GAAG;YAC9C,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAC5C,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,EAAE,IAAI,KAAK,MAAM;YAClB,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;YACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,sBAAsB,CAAC,CACjF,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC1C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,sBAAsB,CACjE,EAAE,gBAAgB,EAAE,QAAQ,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs/promises\";\nimport { FunctionCallingConfigMode } from \"@google/genai\";\nimport { runToolLoop } from \"../ai/toolLoop/toolLoopRunner.js\";\n\ntest(\"tool loop: insert_element failure includes available routes and hint\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-runner-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n // Let's create an existing route\n await fs.mkdir(path.join(workspaceRoot, \"app\", \"dashboard\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"dashboard\", \"pageConfig.json\"), \"{}\");\n\n let aiCalls = 0;\n const aiCall = async () => {\n aiCalls += 1;\n if (aiCalls === 1) {\n return {\n functionCalls: [\n {\n name: \"insert_element\",\n args: {\n route: \"/invalid-route\",\n parent_id: \"root\",\n element: { type: \"text\", props: { text: \"hi\" } },\n },\n },\n ],\n };\n }\n return { functionCalls: [], text: \"ok\" };\n };\n\n const res = await runToolLoop({\n initialContents: [],\n tools: [],\n workspaceRoot,\n aiCall,\n logger: async () => {},\n toolCallingMode: FunctionCallingConfigMode.ANY,\n maxSteps: 5,\n keepFullTrace: false,\n });\n\n assert.equal(res.finalText, \"ok\");\n\n const toolResponses = res.modelContents.filter(\n (c: any) =>\n c?.role === \"user\" &&\n Array.isArray(c?.parts) &&\n c.parts.some((p: any) => p?.functionResponse?.name === \"insert_element\"),\n );\n assert.equal(toolResponses.length, 1);\n\n const response = toolResponses[0].parts.find(\n (p: any) => p?.functionResponse?.name === \"insert_element\",\n )?.functionResponse?.response;\n\n assert.equal(response?.success, false);\n assert.match(String(response?.error ?? \"\"), /insert_element failed/i);\n assert.match(String(response?.error ?? \"\"), /create_new_route/i);\n assert.deepEqual(response?.available_routes, [\"/dashboard\"]);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"tool loop: get_available_routes retrieves routes\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-runner-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"pageConfig.json\"), \"{}\");\n await fs.mkdir(path.join(workspaceRoot, \"app\", \"dashboard\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"dashboard\", \"pageConfig.json\"), \"{}\");\n\n let aiCalls = 0;\n const aiCall = async () => {\n aiCalls += 1;\n if (aiCalls === 1) {\n return {\n functionCalls: [{ name: \"get_available_routes\", args: {} }],\n };\n }\n return { functionCalls: [], text: \"ok\" };\n };\n\n const res = await runToolLoop({\n initialContents: [],\n tools: [],\n workspaceRoot,\n aiCall,\n logger: async () => {},\n toolCallingMode: FunctionCallingConfigMode.ANY,\n maxSteps: 5,\n keepFullTrace: false,\n });\n\n assert.equal(res.finalText, \"ok\");\n\n const toolResponses = res.modelContents.filter(\n (c: any) =>\n c?.role === \"user\" &&\n Array.isArray(c?.parts) &&\n c.parts.some((p: any) => p?.functionResponse?.name === \"get_available_routes\"),\n );\n assert.equal(toolResponses.length, 1);\n\n const response = toolResponses[0].parts.find(\n (p: any) => p?.functionResponse?.name === \"get_available_routes\",\n )?.functionResponse?.response;\n\n assert.equal(response?.success, true);\n assert.deepEqual(response?.routes, [\"/\", \"/dashboard\"]);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n"]}
1
+ {"version":3,"file":"toolLoopRunner.routes.test.js","sourceRoot":"","sources":["../../src/tests/toolLoopRunner.routes.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACtF,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,iCAAiC;QACjC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1F,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,aAAa,EAAE;wBACb;4BACE,IAAI,EAAE,gBAAgB;4BACtB,IAAI,EAAE;gCACJ,KAAK,EAAE,gBAAgB;gCACvB,SAAS,EAAE,MAAM;gCACjB,QAAQ,EAAE;oCACR,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;iCAC3E;6BACF;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;YAC5B,eAAe,EAAE,EAAE;YACnB,KAAK,EAAE,EAAE;YACT,aAAa;YACb,MAAM;YACN,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACtB,eAAe,EAAE,yBAAyB,CAAC,GAAG;YAC9C,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAC5C,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,EAAE,IAAI,KAAK,MAAM;YAClB,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;YACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,gBAAgB,CAAC,CAC3E,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC1C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,gBAAgB,CAC3D,EAAE,gBAAgB,EAAE,QAAQ,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,wBAAwB,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;IAClE,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7E,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1F,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;iBAC5D,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;YAC5B,eAAe,EAAE,EAAE;YACnB,KAAK,EAAE,EAAE;YACT,aAAa;YACb,MAAM;YACN,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACtB,eAAe,EAAE,yBAAyB,CAAC,GAAG;YAC9C,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAC5C,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,EAAE,IAAI,KAAK,MAAM;YAClB,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;YACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,sBAAsB,CAAC,CACjF,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC1C,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,KAAK,sBAAsB,CACjE,EAAE,gBAAgB,EAAE,QAAQ,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs/promises\";\nimport { FunctionCallingConfigMode } from \"@google/genai\";\nimport { runToolLoop } from \"../ai/toolLoop/toolLoopRunner.js\";\n\ntest(\"tool loop: insert_element failure includes available routes and hint\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-runner-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n // Let's create an existing route\n await fs.mkdir(path.join(workspaceRoot, \"app\", \"dashboard\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"dashboard\", \"pageConfig.json\"), \"{}\");\n\n let aiCalls = 0;\n const aiCall = async () => {\n aiCalls += 1;\n if (aiCalls === 1) {\n return {\n functionCalls: [\n {\n name: \"insert_element\",\n args: {\n route: \"/invalid-route\",\n parent_id: \"root\",\n elements: [\n { id: \"text_el\", parentId: \"parent\", type: \"text\", props: { text: \"hi\" } }\n ],\n },\n },\n ],\n };\n }\n return { functionCalls: [], text: \"ok\" };\n };\n\n const res = await runToolLoop({\n initialContents: [],\n tools: [],\n workspaceRoot,\n aiCall,\n logger: async () => {},\n toolCallingMode: FunctionCallingConfigMode.ANY,\n maxSteps: 5,\n keepFullTrace: false,\n });\n\n assert.equal(res.finalText, \"ok\");\n\n const toolResponses = res.modelContents.filter(\n (c: any) =>\n c?.role === \"user\" &&\n Array.isArray(c?.parts) &&\n c.parts.some((p: any) => p?.functionResponse?.name === \"insert_element\"),\n );\n assert.equal(toolResponses.length, 1);\n\n const response = toolResponses[0].parts.find(\n (p: any) => p?.functionResponse?.name === \"insert_element\",\n )?.functionResponse?.response;\n\n assert.equal(response?.success, false);\n assert.match(String(response?.error ?? \"\"), /insert_element failed/i);\n assert.match(String(response?.error ?? \"\"), /create_new_route/i);\n assert.deepEqual(response?.available_routes, [\"/dashboard\"]);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"tool loop: get_available_routes retrieves routes\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-runner-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"pageConfig.json\"), \"{}\");\n await fs.mkdir(path.join(workspaceRoot, \"app\", \"dashboard\"), { recursive: true });\n await fs.writeFile(path.join(workspaceRoot, \"app\", \"dashboard\", \"pageConfig.json\"), \"{}\");\n\n let aiCalls = 0;\n const aiCall = async () => {\n aiCalls += 1;\n if (aiCalls === 1) {\n return {\n functionCalls: [{ name: \"get_available_routes\", args: {} }],\n };\n }\n return { functionCalls: [], text: \"ok\" };\n };\n\n const res = await runToolLoop({\n initialContents: [],\n tools: [],\n workspaceRoot,\n aiCall,\n logger: async () => {},\n toolCallingMode: FunctionCallingConfigMode.ANY,\n maxSteps: 5,\n keepFullTrace: false,\n });\n\n assert.equal(res.finalText, \"ok\");\n\n const toolResponses = res.modelContents.filter(\n (c: any) =>\n c?.role === \"user\" &&\n Array.isArray(c?.parts) &&\n c.parts.some((p: any) => p?.functionResponse?.name === \"get_available_routes\"),\n );\n assert.equal(toolResponses.length, 1);\n\n const response = toolResponses[0].parts.find(\n (p: any) => p?.functionResponse?.name === \"get_available_routes\",\n )?.functionResponse?.response;\n\n assert.equal(response?.success, true);\n assert.deepEqual(response?.routes, [\"/\", \"/dashboard\"]);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toolLoopRunner.tokensPersist.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolLoopRunner.tokensPersist.test.d.ts","sourceRoot":"","sources":["../../src/tests/toolLoopRunner.tokensPersist.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,52 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { FunctionCallingConfigMode } from "@google/genai";
4
+ import { runToolLoop } from "../ai/toolLoop/toolLoopRunner.js";
5
+ test("tool loop: persists gen tokens from usageMetadata", async () => {
6
+ const persisted = [];
7
+ let aiCalls = 0;
8
+ const res = await runToolLoop({
9
+ initialContents: [],
10
+ tools: [],
11
+ workspaceRoot: "/dummy/path",
12
+ toolCallingMode: FunctionCallingConfigMode.ANY,
13
+ maxSteps: 2,
14
+ keepFullTrace: false,
15
+ logger: async () => { },
16
+ aiCall: async () => {
17
+ aiCalls += 1;
18
+ if (aiCalls === 1) {
19
+ return {
20
+ functionCalls: [{ name: "get_available_routes", args: {} }],
21
+ modelVersion: "gemini-2.5-flash-lite",
22
+ usageMetadata: { promptTokenCount: 11, candidatesTokenCount: 22 },
23
+ };
24
+ }
25
+ return {
26
+ functionCalls: [],
27
+ text: "ok",
28
+ modelVersion: "gemini-2.5-flash-lite",
29
+ usageMetadata: { promptTokenCount: 33, candidatesTokenCount: 44 },
30
+ };
31
+ },
32
+ tokenPersistence: {
33
+ sessionId: "sess_123",
34
+ repository: {
35
+ persistGenTokens: async (sessionId, input, output, model) => {
36
+ persisted.push({ sessionId, input, output, model });
37
+ },
38
+ },
39
+ model: 'gemini-2.5-flash-lite'
40
+ },
41
+ });
42
+ assert.equal(res.finalText, "ok");
43
+ assert.deepEqual(persisted, [
44
+ {
45
+ sessionId: "sess_123",
46
+ input: 44,
47
+ output: 66,
48
+ model: "gemini-2.5-flash-lite",
49
+ },
50
+ ]);
51
+ });
52
+ //# sourceMappingURL=toolLoopRunner.tokensPersist.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolLoopRunner.tokensPersist.test.js","sourceRoot":"","sources":["../../src/tests/toolLoopRunner.tokensPersist.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,SAAS,GAKV,EAAE,CAAC;IAER,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC;QAC5B,eAAe,EAAE,EAAE;QACnB,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,aAAa;QAC5B,eAAe,EAAE,yBAAyB,CAAC,GAAG;QAC9C,QAAQ,EAAE,CAAC;QACX,aAAa,EAAE,KAAK;QACpB,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACtB,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;gBAClB,OAAO;oBACL,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;oBAC3D,YAAY,EAAE,uBAAuB;oBACrC,aAAa,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE;iBAClE,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,aAAa,EAAE,EAAE;gBACjB,IAAI,EAAE,IAAI;gBACV,YAAY,EAAE,uBAAuB;gBACrC,aAAa,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE;aAClE,CAAC;QACJ,CAAC;QACD,gBAAgB,EAAE;YAChB,SAAS,EAAE,UAAU;YACrB,UAAU,EAAE;gBACV,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;oBAC1D,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtD,CAAC;aACF;YACD,KAAK,EAAC,uBAAuB;SAC9B;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE;QAC1B;YACE,SAAS,EAAE,UAAU;YACrB,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,uBAAuB;SAC/B;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { FunctionCallingConfigMode } from \"@google/genai\";\nimport { runToolLoop } from \"../ai/toolLoop/toolLoopRunner.js\";\n\ntest(\"tool loop: persists gen tokens from usageMetadata\", async () => {\n const persisted: Array<{\n sessionId: string;\n input: number;\n output: number;\n model: string;\n }> = [];\n\n let aiCalls = 0;\n const res = await runToolLoop({\n initialContents: [],\n tools: [],\n workspaceRoot: \"/dummy/path\",\n toolCallingMode: FunctionCallingConfigMode.ANY,\n maxSteps: 2,\n keepFullTrace: false,\n logger: async () => {},\n aiCall: async () => {\n aiCalls += 1;\n if (aiCalls === 1) {\n return {\n functionCalls: [{ name: \"get_available_routes\", args: {} }],\n modelVersion: \"gemini-2.5-flash-lite\",\n usageMetadata: { promptTokenCount: 11, candidatesTokenCount: 22 },\n };\n }\n return {\n functionCalls: [],\n text: \"ok\",\n modelVersion: \"gemini-2.5-flash-lite\",\n usageMetadata: { promptTokenCount: 33, candidatesTokenCount: 44 },\n };\n },\n tokenPersistence: {\n sessionId: \"sess_123\",\n repository: {\n persistGenTokens: async (sessionId, input, output, model) => {\n persisted.push({ sessionId, input, output, model });\n },\n },\n model:'gemini-2.5-flash-lite'\n },\n });\n\n assert.equal(res.finalText, \"ok\");\n assert.deepEqual(persisted, [\n {\n sessionId: \"sess_123\",\n input: 44,\n output: 66,\n model: \"gemini-2.5-flash-lite\",\n },\n ]);\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedangiitb/qwintly-core",
3
- "version": "1.4.8",
3
+ "version": "1.4.10",
4
4
  "description": "Qwintly Core",
5
5
  "homepage": "https://github.com/vedangiitb/qwintly-core#readme",
6
6
  "bugs": {