@vedangiitb/qwintly-core 1.0.2
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.
- package/README.md +8 -0
- package/dist/ai/ai.d.ts +2 -0
- package/dist/ai/ai.d.ts.map +1 -0
- package/dist/ai/ai.js +2 -0
- package/dist/ai/ai.js.map +1 -0
- package/dist/ai/generate/gemini.client.d.ts +15 -0
- package/dist/ai/generate/gemini.client.d.ts.map +1 -0
- package/dist/ai/generate/gemini.client.js +39 -0
- package/dist/ai/generate/gemini.client.js.map +1 -0
- package/dist/ai/generate/generateClient.d.ts +3 -0
- package/dist/ai/generate/generateClient.d.ts.map +1 -0
- package/dist/ai/generate/generateClient.js +8 -0
- package/dist/ai/generate/generateClient.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopContext.d.ts +33 -0
- package/dist/ai/toolLoop/toolLoopContext.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopContext.js +112 -0
- package/dist/ai/toolLoop/toolLoopContext.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunner.d.ts +43 -0
- package/dist/ai/toolLoop/toolLoopRunner.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunner.js +227 -0
- package/dist/ai/toolLoop/toolLoopRunner.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts +51 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.js +164 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.js.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.d.ts +36 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.js +307 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.d.ts +2 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.d.ts.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.js +50 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.js.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.d.ts +2 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.js +45 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.d.ts +2 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.d.ts.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.js +15 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.js.map +1 -0
- package/dist/ai/tools/helpers/format.helpers.d.ts +2 -0
- package/dist/ai/tools/helpers/format.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/format.helpers.js +14 -0
- package/dist/ai/tools/helpers/format.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.d.ts +8 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.d.ts.map +1 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.js +26 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.js.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.d.ts +53 -0
- package/dist/ai/tools/implementations/applyPatch.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.js +242 -0
- package/dist/ai/tools/implementations/applyPatch.impl.js.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.d.ts +2 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.d.ts.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.js +72 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.js.map +1 -0
- package/dist/ai/tools/implementations/factories.d.ts +90 -0
- package/dist/ai/tools/implementations/factories.d.ts.map +1 -0
- package/dist/ai/tools/implementations/factories.js +26 -0
- package/dist/ai/tools/implementations/factories.js.map +1 -0
- package/dist/ai/tools/implementations/listDir.impl.d.ts +3 -0
- package/dist/ai/tools/implementations/listDir.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/listDir.impl.js +47 -0
- package/dist/ai/tools/implementations/listDir.impl.js.map +1 -0
- package/dist/ai/tools/implementations/readFile.impl.d.ts +3 -0
- package/dist/ai/tools/implementations/readFile.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/readFile.impl.js +23 -0
- package/dist/ai/tools/implementations/readFile.impl.js.map +1 -0
- package/dist/ai/tools/implementations/search.impl.d.ts +18 -0
- package/dist/ai/tools/implementations/search.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/search.impl.js +74 -0
- package/dist/ai/tools/implementations/search.impl.js.map +1 -0
- package/dist/ai/tools/implementations/workspaceDeps.d.ts +22 -0
- package/dist/ai/tools/implementations/workspaceDeps.d.ts.map +1 -0
- package/dist/ai/tools/implementations/workspaceDeps.js +2 -0
- package/dist/ai/tools/implementations/workspaceDeps.js.map +1 -0
- package/dist/ai/tools/implementations/writeFile.impl.d.ts +27 -0
- package/dist/ai/tools/implementations/writeFile.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/writeFile.impl.js +62 -0
- package/dist/ai/tools/implementations/writeFile.impl.js.map +1 -0
- package/dist/ai/tools/schemas/applyPatch.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/applyPatch.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/applyPatch.schema.js +17 -0
- package/dist/ai/tools/schemas/applyPatch.schema.js.map +1 -0
- package/dist/ai/tools/schemas/listDir.schema.d.ts +22 -0
- package/dist/ai/tools/schemas/listDir.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/listDir.schema.js +22 -0
- package/dist/ai/tools/schemas/listDir.schema.js.map +1 -0
- package/dist/ai/tools/schemas/readFile.schema.d.ts +26 -0
- package/dist/ai/tools/schemas/readFile.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/readFile.schema.js +26 -0
- package/dist/ai/tools/schemas/readFile.schema.js.map +1 -0
- package/dist/ai/tools/schemas/search.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/search.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/search.schema.js +16 -0
- package/dist/ai/tools/schemas/search.schema.js.map +1 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.js +16 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.js.map +1 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.d.ts +33 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.js +31 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.js.map +1 -0
- package/dist/ai/tools/schemas/writeFile.schema.d.ts +20 -0
- package/dist/ai/tools/schemas/writeFile.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/writeFile.schema.js +23 -0
- package/dist/ai/tools/schemas/writeFile.schema.js.map +1 -0
- package/dist/ai/tools/toolsets/codegenTools.d.ts +3 -0
- package/dist/ai/tools/toolsets/codegenTools.d.ts.map +1 -0
- package/dist/ai/tools/toolsets/codegenTools.js +17 -0
- package/dist/ai/tools/toolsets/codegenTools.js.map +1 -0
- package/dist/ai/tools/toolsets/plannerTools.d.ts +3 -0
- package/dist/ai/tools/toolsets/plannerTools.d.ts.map +1 -0
- package/dist/ai/tools/toolsets/plannerTools.js +17 -0
- package/dist/ai/tools/toolsets/plannerTools.js.map +1 -0
- package/dist/core.d.ts +44 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +80 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/codegenIndex.d.ts +3 -0
- package/dist/indexer/codegenIndex.d.ts.map +1 -0
- package/dist/indexer/codegenIndex.js +17 -0
- package/dist/indexer/codegenIndex.js.map +1 -0
- package/dist/indexer/data/configs.constants.d.ts +85 -0
- package/dist/indexer/data/configs.constants.d.ts.map +1 -0
- package/dist/indexer/data/configs.constants.js +136 -0
- package/dist/indexer/data/configs.constants.js.map +1 -0
- package/dist/indexer/helpers/buildFolderTree.d.ts +2 -0
- package/dist/indexer/helpers/buildFolderTree.d.ts.map +1 -0
- package/dist/indexer/helpers/buildFolderTree.js +40 -0
- package/dist/indexer/helpers/buildFolderTree.js.map +1 -0
- package/dist/indexer/plannerIndex.d.ts +3 -0
- package/dist/indexer/plannerIndex.d.ts.map +1 -0
- package/dist/indexer/plannerIndex.js +20 -0
- package/dist/indexer/plannerIndex.js.map +1 -0
- package/dist/indexer/projectInfoIndex.d.ts +3 -0
- package/dist/indexer/projectInfoIndex.d.ts.map +1 -0
- package/dist/indexer/projectInfoIndex.js +257 -0
- package/dist/indexer/projectInfoIndex.js.map +1 -0
- package/dist/indexer/validatorIndex.d.ts +3 -0
- package/dist/indexer/validatorIndex.d.ts.map +1 -0
- package/dist/indexer/validatorIndex.js +14 -0
- package/dist/indexer/validatorIndex.js.map +1 -0
- package/dist/lib/redis.d.ts +3 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +7 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/supabase.d.ts +2 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +4 -0
- package/dist/lib/supabase.js.map +1 -0
- package/dist/logging/genStatus.service.d.ts +14 -0
- package/dist/logging/genStatus.service.d.ts.map +1 -0
- package/dist/logging/genStatus.service.js +36 -0
- package/dist/logging/genStatus.service.js.map +1 -0
- package/dist/logging/logging.utils.d.ts +12 -0
- package/dist/logging/logging.utils.d.ts.map +1 -0
- package/dist/logging/logging.utils.js +15 -0
- package/dist/logging/logging.utils.js.map +1 -0
- package/dist/logging/redis.service.d.ts +11 -0
- package/dist/logging/redis.service.d.ts.map +1 -0
- package/dist/logging/redis.service.js +26 -0
- package/dist/logging/redis.service.js.map +1 -0
- package/dist/repository/context.repository.d.ts +8 -0
- package/dist/repository/context.repository.d.ts.map +1 -0
- package/dist/repository/context.repository.js +59 -0
- package/dist/repository/context.repository.js.map +1 -0
- package/dist/repository/genStatus.repository.d.ts +13 -0
- package/dist/repository/genStatus.repository.d.ts.map +1 -0
- package/dist/repository/genStatus.repository.js +18 -0
- package/dist/repository/genStatus.repository.js.map +1 -0
- package/dist/repository/planTasks.repository.d.ts +9 -0
- package/dist/repository/planTasks.repository.d.ts.map +1 -0
- package/dist/repository/planTasks.repository.js +24 -0
- package/dist/repository/planTasks.repository.js.map +1 -0
- package/dist/repository/repository.d.ts +5 -0
- package/dist/repository/repository.d.ts.map +1 -0
- package/dist/repository/repository.js +7 -0
- package/dist/repository/repository.js.map +1 -0
- package/dist/types/context.types.d.ts +64 -0
- package/dist/types/context.types.d.ts.map +1 -0
- package/dist/types/context.types.js +55 -0
- package/dist/types/context.types.js.map +1 -0
- package/dist/types/events.d.ts +16 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +14 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index/configs.types.d.ts +28 -0
- package/dist/types/index/configs.types.d.ts.map +1 -0
- package/dist/types/index/configs.types.js +2 -0
- package/dist/types/index/configs.types.js.map +1 -0
- package/dist/types/index/conventions.types.d.ts +40 -0
- package/dist/types/index/conventions.types.d.ts.map +1 -0
- package/dist/types/index/conventions.types.js +2 -0
- package/dist/types/index/conventions.types.js.map +1 -0
- package/dist/types/index/index.types.d.ts +16 -0
- package/dist/types/index/index.types.d.ts.map +1 -0
- package/dist/types/index/index.types.js +2 -0
- package/dist/types/index/index.types.js.map +1 -0
- package/dist/types/index/indexing.types.d.ts +9 -0
- package/dist/types/index/indexing.types.d.ts.map +1 -0
- package/dist/types/index/indexing.types.js +2 -0
- package/dist/types/index/indexing.types.js.map +1 -0
- package/dist/types/projectInfo.types.d.ts +16 -0
- package/dist/types/projectInfo.types.d.ts.map +1 -0
- package/dist/types/projectInfo.types.js +2 -0
- package/dist/types/projectInfo.types.js.map +1 -0
- package/dist/types/updatePlan.types.d.ts +34 -0
- package/dist/types/updatePlan.types.d.ts.map +1 -0
- package/dist/types/updatePlan.types.js +18 -0
- package/dist/types/updatePlan.types.js.map +1 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +6 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/utils/workspace.d.ts +13 -0
- package/dist/utils/workspace.d.ts.map +1 -0
- package/dist/utils/workspace.js +92 -0
- package/dist/utils/workspace.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
package/dist/ai/ai.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/ai/ai.ts"],"names":[],"mappings":""}
|
package/dist/ai/ai.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/ai/ai.ts"],"names":[],"mappings":"","sourcesContent":[""]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FunctionCallingConfigMode, GoogleGenAI, Tool } from "@google/genai";
|
|
2
|
+
import type { ZodSchema } from "zod";
|
|
3
|
+
type AIResponseOptions = {
|
|
4
|
+
tools?: Tool[];
|
|
5
|
+
schema?: ZodSchema;
|
|
6
|
+
toolCallingMode?: FunctionCallingConfigMode;
|
|
7
|
+
};
|
|
8
|
+
export declare class GenerateGeminiReponse {
|
|
9
|
+
gemini: GoogleGenAI;
|
|
10
|
+
model: string;
|
|
11
|
+
constructor(geminiApiKey: string, model?: string);
|
|
12
|
+
aiResponse(request: unknown, options?: AIResponseOptions): Promise<import("@google/genai").GenerateContentResponse>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=gemini.client.d.ts.map
|
|
@@ -0,0 +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;CAmC1E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { FunctionCallingConfigMode, GoogleGenAI, } from "@google/genai";
|
|
2
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
|
+
const DEFAULT_MODEL = "gemini-2.5-flash-lite";
|
|
4
|
+
export class GenerateGeminiReponse {
|
|
5
|
+
constructor(geminiApiKey, model) {
|
|
6
|
+
this.model = DEFAULT_MODEL;
|
|
7
|
+
this.gemini = new GoogleGenAI({ apiKey: geminiApiKey });
|
|
8
|
+
if (model) {
|
|
9
|
+
this.model = model;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async aiResponse(request, options = {}) {
|
|
13
|
+
const { tools, schema, toolCallingMode = FunctionCallingConfigMode.AUTO, } = options;
|
|
14
|
+
const config = {};
|
|
15
|
+
if (tools && tools.length > 0) {
|
|
16
|
+
config.tools = tools;
|
|
17
|
+
config.toolConfig = {
|
|
18
|
+
functionCallingConfig: {
|
|
19
|
+
mode: toolCallingMode,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (schema) {
|
|
24
|
+
config.responseMimeType = "application/json";
|
|
25
|
+
config.responseJsonSchema = zodToJsonSchema(schema);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return await this.gemini.models.generateContent({
|
|
29
|
+
model: this.model,
|
|
30
|
+
contents: request,
|
|
31
|
+
...(Object.keys(config).length > 0 && { config }),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
throw new Error(`AI generation failed: ${err?.message || "Unknown error"}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=gemini.client.js.map
|
|
@@ -0,0 +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,IAAI,KAAK,CACb,yBAAyB,GAAG,EAAE,OAAO,IAAI,eAAe,EAAE,CAC3D,CAAC;QACJ,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 throw new Error(\n `AI generation failed: ${err?.message || \"Unknown error\"}`,\n );\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateClient.d.ts","sourceRoot":"","sources":["../../../src/ai/generate/generateClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,QAAQ,MAAM,0BAMf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GenerateGeminiReponse } from "./gemini.client.js";
|
|
2
|
+
export const getClient = (provider, apiKey, model) => {
|
|
3
|
+
if (provider === "gemini") {
|
|
4
|
+
return new GenerateGeminiReponse(apiKey, model);
|
|
5
|
+
}
|
|
6
|
+
throw new Error(`Unknown provider: ${provider}`);
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=generateClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateClient.js","sourceRoot":"","sources":["../../../src/ai/generate/generateClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,QAAgB,EAChB,MAAc,EACd,KAAc,EACd,EAAE;IACF,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC","sourcesContent":["import { GenerateGeminiReponse } from \"./gemini.client.js\";\r\n\r\nexport const getClient = (\r\n provider: string,\r\n apiKey: string,\r\n model?: string,\r\n) => {\r\n if (provider === \"gemini\") {\r\n return new GenerateGeminiReponse(apiKey, model);\r\n }\r\n throw new Error(`Unknown provider: ${provider}`);\r\n};\r\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type ToolEvent = {
|
|
2
|
+
name: string;
|
|
3
|
+
summary: string;
|
|
4
|
+
};
|
|
5
|
+
export type ToolLoopContextPolicy = {
|
|
6
|
+
readFileDefaultMaxLines?: number;
|
|
7
|
+
tailMessages?: number;
|
|
8
|
+
maxModelChars?: number;
|
|
9
|
+
logApproxModelChars?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const DEFAULT_CONTEXT_POLICY: Required<ToolLoopContextPolicy>;
|
|
12
|
+
export declare const redactFunctionCallArgs: (name: string, args: Record<string, unknown>) => Record<string, unknown>;
|
|
13
|
+
export declare const compactForModel: (input: {
|
|
14
|
+
initialCount: number;
|
|
15
|
+
modelContents: any[];
|
|
16
|
+
toolEvents: ToolEvent[];
|
|
17
|
+
policy: Required<ToolLoopContextPolicy>;
|
|
18
|
+
}) => any[];
|
|
19
|
+
export declare const normalizeReadFileArgs: (args: Record<string, unknown>, maxLines: number) => {
|
|
20
|
+
effectiveArgs: {
|
|
21
|
+
start_line: number;
|
|
22
|
+
end_line: number;
|
|
23
|
+
};
|
|
24
|
+
start: number;
|
|
25
|
+
end: number;
|
|
26
|
+
wasCapped: boolean;
|
|
27
|
+
};
|
|
28
|
+
export declare const getApplyPatchEventMeta: (args: Record<string, unknown>) => {
|
|
29
|
+
chars: number;
|
|
30
|
+
sha256: string;
|
|
31
|
+
files: string[];
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=toolLoopContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolLoopContext.d.ts","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopContext.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,qBAAqB,CAKlE,CAAC;AAuBF,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,4BAqB9B,CAAC;AAiBF,eAAO,MAAM,eAAe,GAAI,OAAO;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,GAAG,EAAE,CAAC;IACrB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;CACzC,UA8BA,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,MAAM;;;;;;;;CAmCjB,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;CAOnE,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
export const DEFAULT_CONTEXT_POLICY = {
|
|
3
|
+
readFileDefaultMaxLines: 200,
|
|
4
|
+
tailMessages: 12,
|
|
5
|
+
maxModelChars: 120000,
|
|
6
|
+
logApproxModelChars: false,
|
|
7
|
+
};
|
|
8
|
+
const sha256Hex = (value) => crypto.createHash("sha256").update(value, "utf8").digest("hex");
|
|
9
|
+
const extractPatchFiles = (patchString) => {
|
|
10
|
+
const lines = patchString.replace(/\r\n/g, "\n").split("\n");
|
|
11
|
+
const files = new Set();
|
|
12
|
+
for (const line of lines) {
|
|
13
|
+
const match = /^\*\*\* (Update File|Add File|Delete File):\s+(.+)$/.exec(line) ??
|
|
14
|
+
/^\*\*\* Move to:\s+(.+)$/.exec(line);
|
|
15
|
+
if (!match)
|
|
16
|
+
continue;
|
|
17
|
+
const filePath = (match[2] ?? match[1] ?? "").trim();
|
|
18
|
+
if (filePath)
|
|
19
|
+
files.add(filePath);
|
|
20
|
+
}
|
|
21
|
+
return [...files];
|
|
22
|
+
};
|
|
23
|
+
export const redactFunctionCallArgs = (name, args) => {
|
|
24
|
+
if (name !== "apply_patch")
|
|
25
|
+
return args;
|
|
26
|
+
const patch = typeof args.patch_string === "string" ? args.patch_string : "";
|
|
27
|
+
if (!patch) {
|
|
28
|
+
return {
|
|
29
|
+
...args,
|
|
30
|
+
patch_string: { omitted: true, chars: 0, sha256: sha256Hex(""), files: [] },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
...args,
|
|
35
|
+
patch_string: {
|
|
36
|
+
omitted: true,
|
|
37
|
+
chars: patch.length,
|
|
38
|
+
sha256: sha256Hex(patch),
|
|
39
|
+
files: extractPatchFiles(patch),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const isMemoryMessage = (item) => {
|
|
44
|
+
const text = item?.parts?.[0]?.text;
|
|
45
|
+
return (item?.role === "model" &&
|
|
46
|
+
typeof text === "string" &&
|
|
47
|
+
text.startsWith("MEMORY (tool trace summary):"));
|
|
48
|
+
};
|
|
49
|
+
const buildMemoryText = (events) => {
|
|
50
|
+
if (events.length === 0)
|
|
51
|
+
return "";
|
|
52
|
+
const lines = events.map((e) => `- ${e.summary}`);
|
|
53
|
+
return `MEMORY (tool trace summary):\n${lines.join("\n")}`;
|
|
54
|
+
};
|
|
55
|
+
export const compactForModel = (input) => {
|
|
56
|
+
const { initialCount, modelContents, toolEvents, policy } = input;
|
|
57
|
+
const withoutOldMemory = modelContents.filter((c) => !isMemoryMessage(c));
|
|
58
|
+
const tailStart = Math.max(initialCount, withoutOldMemory.length - policy.tailMessages);
|
|
59
|
+
const initial = withoutOldMemory.slice(0, initialCount);
|
|
60
|
+
const tail = withoutOldMemory.slice(tailStart);
|
|
61
|
+
const memoryText = buildMemoryText(toolEvents);
|
|
62
|
+
const memory = memoryText
|
|
63
|
+
? [{ role: "model", parts: [{ text: memoryText }] }]
|
|
64
|
+
: [];
|
|
65
|
+
let compacted = [...initial, ...memory, ...tail];
|
|
66
|
+
const maxChars = Math.max(10000, policy.maxModelChars);
|
|
67
|
+
while (JSON.stringify(compacted).length > maxChars) {
|
|
68
|
+
const minLen = initial.length + memory.length + 1;
|
|
69
|
+
if (compacted.length <= minLen)
|
|
70
|
+
break;
|
|
71
|
+
compacted = [
|
|
72
|
+
...initial,
|
|
73
|
+
...memory,
|
|
74
|
+
...compacted.slice(initial.length + memory.length + 1),
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
return compacted;
|
|
78
|
+
};
|
|
79
|
+
export const normalizeReadFileArgs = (args, maxLines) => {
|
|
80
|
+
const requestedStart = args.start_line === undefined || args.start_line === null
|
|
81
|
+
? 1
|
|
82
|
+
: Number(args.start_line);
|
|
83
|
+
const requestedEnd = args.end_line === undefined || args.end_line === null
|
|
84
|
+
? undefined
|
|
85
|
+
: Number(args.end_line);
|
|
86
|
+
const start = Number.isFinite(requestedStart) && requestedStart > 0 ? requestedStart : 1;
|
|
87
|
+
const cap = Math.max(1, Math.floor(maxLines));
|
|
88
|
+
const desiredEnd = requestedEnd === undefined ||
|
|
89
|
+
!Number.isFinite(requestedEnd) ||
|
|
90
|
+
requestedEnd < start
|
|
91
|
+
? start + cap - 1
|
|
92
|
+
: requestedEnd;
|
|
93
|
+
const cappedEnd = Math.min(desiredEnd, start + cap - 1);
|
|
94
|
+
const wasCapped = requestedEnd === undefined ||
|
|
95
|
+
desiredEnd !== requestedEnd ||
|
|
96
|
+
cappedEnd !== desiredEnd;
|
|
97
|
+
return {
|
|
98
|
+
effectiveArgs: { ...args, start_line: start, end_line: cappedEnd },
|
|
99
|
+
start,
|
|
100
|
+
end: cappedEnd,
|
|
101
|
+
wasCapped,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export const getApplyPatchEventMeta = (args) => {
|
|
105
|
+
const patch = typeof args.patch_string === "string" ? args.patch_string : "";
|
|
106
|
+
return {
|
|
107
|
+
chars: patch.length,
|
|
108
|
+
sha256: sha256Hex(patch),
|
|
109
|
+
files: extractPatchFiles(patch),
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=toolLoopContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolLoopContext.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopContext.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\n\nexport type ToolEvent = {\n name: string;\n summary: string;\n};\n\nexport type ToolLoopContextPolicy = {\n readFileDefaultMaxLines?: number;\n tailMessages?: number;\n maxModelChars?: number;\n logApproxModelChars?: boolean;\n};\n\nexport const DEFAULT_CONTEXT_POLICY: Required<ToolLoopContextPolicy> = {\n readFileDefaultMaxLines: 200,\n tailMessages: 12,\n maxModelChars: 120_000,\n logApproxModelChars: false,\n};\n\nconst sha256Hex = (value: string) =>\n crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n\nconst extractPatchFiles = (patchString: string): string[] => {\n const lines = patchString.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const files = new Set<string>();\n\n for (const line of lines) {\n const match =\n /^\\*\\*\\* (Update File|Add File|Delete File):\\s+(.+)$/.exec(line) ??\n /^\\*\\*\\* Move to:\\s+(.+)$/.exec(line);\n\n if (!match) continue;\n\n const filePath = (match[2] ?? match[1] ?? \"\").trim();\n if (filePath) files.add(filePath);\n }\n\n return [...files];\n};\n\nexport const redactFunctionCallArgs = (\n name: string,\n args: Record<string, unknown>,\n) => {\n if (name !== \"apply_patch\") return args;\n\n const patch = typeof args.patch_string === \"string\" ? args.patch_string : \"\";\n if (!patch) {\n return {\n ...args,\n patch_string: { omitted: true, chars: 0, sha256: sha256Hex(\"\"), files: [] },\n };\n }\n\n return {\n ...args,\n patch_string: {\n omitted: true,\n chars: patch.length,\n sha256: sha256Hex(patch),\n files: extractPatchFiles(patch),\n },\n };\n};\n\nconst isMemoryMessage = (item: any) => {\n const text = item?.parts?.[0]?.text;\n return (\n item?.role === \"model\" &&\n typeof text === \"string\" &&\n text.startsWith(\"MEMORY (tool trace summary):\")\n );\n};\n\nconst buildMemoryText = (events: ToolEvent[]) => {\n if (events.length === 0) return \"\";\n const lines = events.map((e) => `- ${e.summary}`);\n return `MEMORY (tool trace summary):\\n${lines.join(\"\\n\")}`;\n};\n\nexport const compactForModel = (input: {\n initialCount: number;\n modelContents: any[];\n toolEvents: ToolEvent[];\n policy: Required<ToolLoopContextPolicy>;\n}) => {\n const { initialCount, modelContents, toolEvents, policy } = input;\n\n const withoutOldMemory = modelContents.filter((c) => !isMemoryMessage(c));\n const tailStart = Math.max(\n initialCount,\n withoutOldMemory.length - policy.tailMessages,\n );\n\n const initial = withoutOldMemory.slice(0, initialCount);\n const tail = withoutOldMemory.slice(tailStart);\n const memoryText = buildMemoryText(toolEvents);\n const memory = memoryText\n ? [{ role: \"model\", parts: [{ text: memoryText }] }]\n : [];\n\n let compacted = [...initial, ...memory, ...tail];\n\n const maxChars = Math.max(10_000, policy.maxModelChars);\n while (JSON.stringify(compacted).length > maxChars) {\n const minLen = initial.length + memory.length + 1;\n if (compacted.length <= minLen) break;\n compacted = [\n ...initial,\n ...memory,\n ...compacted.slice(initial.length + memory.length + 1),\n ];\n }\n\n return compacted;\n};\n\nexport const normalizeReadFileArgs = (\n args: Record<string, unknown>,\n maxLines: number,\n) => {\n const requestedStart =\n args.start_line === undefined || args.start_line === null\n ? 1\n : Number(args.start_line);\n\n const requestedEnd =\n args.end_line === undefined || args.end_line === null\n ? undefined\n : Number(args.end_line);\n\n const start =\n Number.isFinite(requestedStart) && requestedStart > 0 ? requestedStart : 1;\n const cap = Math.max(1, Math.floor(maxLines));\n\n const desiredEnd =\n requestedEnd === undefined ||\n !Number.isFinite(requestedEnd) ||\n requestedEnd < start\n ? start + cap - 1\n : requestedEnd;\n\n const cappedEnd = Math.min(desiredEnd, start + cap - 1);\n const wasCapped =\n requestedEnd === undefined ||\n desiredEnd !== requestedEnd ||\n cappedEnd !== desiredEnd;\n\n return {\n effectiveArgs: { ...args, start_line: start, end_line: cappedEnd },\n start,\n end: cappedEnd,\n wasCapped,\n };\n};\n\nexport const getApplyPatchEventMeta = (args: Record<string, unknown>) => {\n const patch = typeof args.patch_string === \"string\" ? args.patch_string : \"\";\n return {\n chars: patch.length,\n sha256: sha256Hex(patch),\n files: extractPatchFiles(patch),\n };\n};\n\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { FunctionCallingConfigMode, Tool } from "@google/genai";
|
|
2
|
+
import { EventType } from "../../types/events.js";
|
|
3
|
+
import { ToolLoopContextPolicy } from "./toolLoopContext.js";
|
|
4
|
+
export type ToolHandler = (args: Record<string, unknown>) => Promise<unknown>;
|
|
5
|
+
export type ToolLoopResult = {
|
|
6
|
+
contents: any[];
|
|
7
|
+
modelContents: any[];
|
|
8
|
+
finalText: string;
|
|
9
|
+
steps: number;
|
|
10
|
+
terminalCall?: {
|
|
11
|
+
name: string;
|
|
12
|
+
args: Record<string, unknown>;
|
|
13
|
+
response: unknown;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export type Logger = (message: string, eventType: EventType) => Promise<void>;
|
|
17
|
+
export type AiCallResponse = {
|
|
18
|
+
functionCalls?: any[];
|
|
19
|
+
text?: string;
|
|
20
|
+
};
|
|
21
|
+
export type AiCallFn = (request: unknown, options: {
|
|
22
|
+
tools?: Tool[];
|
|
23
|
+
model?: string;
|
|
24
|
+
toolCallingMode?: FunctionCallingConfigMode;
|
|
25
|
+
}) => Promise<AiCallResponse>;
|
|
26
|
+
export type RunToolLoopOptions = {
|
|
27
|
+
initialContents: any[];
|
|
28
|
+
tools: Tool[];
|
|
29
|
+
handlers: Record<string, ToolHandler>;
|
|
30
|
+
maxSteps?: number;
|
|
31
|
+
toolCallingMode?: FunctionCallingConfigMode;
|
|
32
|
+
terminalToolNames?: string[];
|
|
33
|
+
keepFullTrace?: boolean;
|
|
34
|
+
contextPolicy?: ToolLoopContextPolicy;
|
|
35
|
+
aiCall: AiCallFn;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
applyPatchAutoRetryMax?: number;
|
|
38
|
+
aiCallAutoRetryMax?: number;
|
|
39
|
+
aiCallAutoRetryBaseMs?: number;
|
|
40
|
+
aiCallAutoRetryMaxMs?: number;
|
|
41
|
+
};
|
|
42
|
+
export declare function runToolLoop(options: RunToolLoopOptions): Promise<ToolLoopResult>;
|
|
43
|
+
//# sourceMappingURL=toolLoopRunner.d.ts.map
|
|
@@ -0,0 +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;AAChE,OAAO,EAAe,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAML,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9E,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,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACtC,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;CAC/B,CAAC;AAEF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CA2RzB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { FunctionCallingConfigMode } from "@google/genai";
|
|
2
|
+
import { EVENT_TYPES } from "../../types/events.js";
|
|
3
|
+
import { compactForModel, DEFAULT_CONTEXT_POLICY, normalizeReadFileArgs, redactFunctionCallArgs, } from "./toolLoopContext.js";
|
|
4
|
+
import { aiCallWithRetry, buildToolStatusMessage, recordToolEvent, serializeError, } from "./toolLoopRunnerUtils.js";
|
|
5
|
+
export async function runToolLoop(options) {
|
|
6
|
+
const { initialContents, tools, handlers, 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
|
|
7
|
+
aiCallAutoRetryBaseMs = 400, aiCallAutoRetryMaxMs = 10000, } = options;
|
|
8
|
+
if (typeof aiCall !== "function") {
|
|
9
|
+
throw new Error("Tool loop: aiCall is required.");
|
|
10
|
+
}
|
|
11
|
+
const policy = {
|
|
12
|
+
...DEFAULT_CONTEXT_POLICY,
|
|
13
|
+
...(contextPolicy ?? {}),
|
|
14
|
+
};
|
|
15
|
+
const toolEvents = [];
|
|
16
|
+
let applyPatchRetryCount = 0;
|
|
17
|
+
const fullTraceContents = keepFullTrace ? [...initialContents] : [];
|
|
18
|
+
let modelContents = [...initialContents];
|
|
19
|
+
const pushBoth = (fullItem, modelItem) => {
|
|
20
|
+
if (keepFullTrace)
|
|
21
|
+
fullTraceContents.push(fullItem);
|
|
22
|
+
modelContents.push(modelItem);
|
|
23
|
+
};
|
|
24
|
+
const pushModelOnly = (modelItem) => {
|
|
25
|
+
modelContents.push(modelItem);
|
|
26
|
+
};
|
|
27
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
28
|
+
modelContents = compactForModel({
|
|
29
|
+
initialCount: initialContents.length,
|
|
30
|
+
modelContents,
|
|
31
|
+
toolEvents,
|
|
32
|
+
policy,
|
|
33
|
+
});
|
|
34
|
+
if (policy.logApproxModelChars) {
|
|
35
|
+
const approxChars = JSON.stringify(modelContents).length;
|
|
36
|
+
console.log("Tool loop: approx model chars", {
|
|
37
|
+
approxChars,
|
|
38
|
+
step: step + 1,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
let response;
|
|
42
|
+
response = await aiCallWithRetry({
|
|
43
|
+
aiCall,
|
|
44
|
+
request: modelContents,
|
|
45
|
+
options: { tools, toolCallingMode },
|
|
46
|
+
retryMax: aiCallAutoRetryMax,
|
|
47
|
+
retryBaseMs: aiCallAutoRetryBaseMs,
|
|
48
|
+
retryMaxMs: aiCallAutoRetryMaxMs,
|
|
49
|
+
step: step + 1,
|
|
50
|
+
logger,
|
|
51
|
+
});
|
|
52
|
+
const functionCalls = response.functionCalls ?? [];
|
|
53
|
+
if (functionCalls.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
contents: keepFullTrace ? fullTraceContents : modelContents,
|
|
56
|
+
modelContents,
|
|
57
|
+
finalText: (response.text ?? "").trim(),
|
|
58
|
+
steps: step + 1,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
for (const call of functionCalls) {
|
|
62
|
+
const name = call.name?.toString() ?? "";
|
|
63
|
+
const args = (call.args ?? {});
|
|
64
|
+
if (!name) {
|
|
65
|
+
throw new Error("Tool loop: function call missing name.");
|
|
66
|
+
}
|
|
67
|
+
const handler = handlers[name];
|
|
68
|
+
const handlerMissingResult = !handler
|
|
69
|
+
? {
|
|
70
|
+
success: false,
|
|
71
|
+
error: `No handler registered for "${name}".`,
|
|
72
|
+
error_detail: {
|
|
73
|
+
name: "MissingToolHandlerError",
|
|
74
|
+
message: `No handler registered for "${name}".`,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
: null;
|
|
78
|
+
let effectiveArgs = args;
|
|
79
|
+
let readFileMeta = null;
|
|
80
|
+
if (name === "read_file") {
|
|
81
|
+
const normalized = normalizeReadFileArgs(effectiveArgs, policy.readFileDefaultMaxLines);
|
|
82
|
+
effectiveArgs = normalized.effectiveArgs;
|
|
83
|
+
readFileMeta = {
|
|
84
|
+
start: normalized.start,
|
|
85
|
+
end: normalized.end,
|
|
86
|
+
wasCapped: normalized.wasCapped,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
logger(buildToolStatusMessage(name, effectiveArgs, readFileMeta), EVENT_TYPES.STEP_STARTED);
|
|
90
|
+
const modelArgs = redactFunctionCallArgs(name, effectiveArgs);
|
|
91
|
+
const assistantFull = {
|
|
92
|
+
role: "model",
|
|
93
|
+
parts: [
|
|
94
|
+
{
|
|
95
|
+
functionCall: {
|
|
96
|
+
name,
|
|
97
|
+
args: effectiveArgs,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
const assistantModel = {
|
|
103
|
+
role: "model",
|
|
104
|
+
parts: [
|
|
105
|
+
{
|
|
106
|
+
functionCall: {
|
|
107
|
+
name,
|
|
108
|
+
args: modelArgs,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
};
|
|
113
|
+
if (keepFullTrace) {
|
|
114
|
+
pushBoth(assistantFull, assistantModel);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
pushModelOnly(assistantModel);
|
|
118
|
+
}
|
|
119
|
+
let toolResultRaw;
|
|
120
|
+
if (handlerMissingResult) {
|
|
121
|
+
toolResultRaw = handlerMissingResult;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
try {
|
|
125
|
+
toolResultRaw = await handler(effectiveArgs);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
logger(`AI tool: ${name} failed`, EVENT_TYPES.STEP_ERROR);
|
|
129
|
+
console.error("Tool loop: handler threw", err, {
|
|
130
|
+
tool: name,
|
|
131
|
+
step: step + 1,
|
|
132
|
+
});
|
|
133
|
+
toolResultRaw = {
|
|
134
|
+
success: false,
|
|
135
|
+
error: err instanceof Error ? err.message : String(err),
|
|
136
|
+
error_detail: serializeError(err),
|
|
137
|
+
note: "Tool handler threw. Inspect error_detail and retry with corrected args or a different approach.",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
let toolResult = toolResultRaw;
|
|
142
|
+
if (name === "read_file" && readFileMeta) {
|
|
143
|
+
const path = String(effectiveArgs.path ?? "");
|
|
144
|
+
const rawContent = typeof toolResultRaw?.content === "string"
|
|
145
|
+
? String(toolResultRaw.content)
|
|
146
|
+
: typeof toolResultRaw === "string"
|
|
147
|
+
? toolResultRaw
|
|
148
|
+
: JSON.stringify(toolResultRaw ?? null);
|
|
149
|
+
toolResult = {
|
|
150
|
+
path,
|
|
151
|
+
start_line: readFileMeta.start,
|
|
152
|
+
end_line: readFileMeta.end,
|
|
153
|
+
truncated: readFileMeta.wasCapped,
|
|
154
|
+
content: rawContent,
|
|
155
|
+
note: readFileMeta.wasCapped
|
|
156
|
+
? `Capped to ${policy.readFileDefaultMaxLines} lines. Request more with start_line/end_line.`
|
|
157
|
+
: undefined,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const responseFull = {
|
|
161
|
+
role: "user",
|
|
162
|
+
parts: [
|
|
163
|
+
{
|
|
164
|
+
functionResponse: {
|
|
165
|
+
name,
|
|
166
|
+
response: toolResult,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
if (keepFullTrace) {
|
|
172
|
+
fullTraceContents.push(responseFull);
|
|
173
|
+
}
|
|
174
|
+
modelContents.push(responseFull);
|
|
175
|
+
if (name === "apply_patch" &&
|
|
176
|
+
toolResult?.success === false &&
|
|
177
|
+
applyPatchAutoRetryMax > 0 &&
|
|
178
|
+
applyPatchRetryCount < applyPatchAutoRetryMax) {
|
|
179
|
+
applyPatchRetryCount += 1;
|
|
180
|
+
const error = String(toolResult?.error ?? "unknown error");
|
|
181
|
+
const debugFiles = Array.isArray(toolResult?.debug?.files)
|
|
182
|
+
? toolResult.debug.files
|
|
183
|
+
: [];
|
|
184
|
+
const debugText = debugFiles.length > 0
|
|
185
|
+
? `\n\nFILE SNAPSHOTS (for regenerating the patch):\n${debugFiles
|
|
186
|
+
.slice(0, 3)
|
|
187
|
+
.map((f) => `--- ${String(f.path ?? "")} ---\n${String(f.head ?? "")}\n--- end ---`)
|
|
188
|
+
.join("\n\n")}`
|
|
189
|
+
: "";
|
|
190
|
+
const retryInstruction = {
|
|
191
|
+
role: "user",
|
|
192
|
+
parts: [
|
|
193
|
+
{
|
|
194
|
+
text: `apply_patch failed (attempt ${applyPatchRetryCount}/${applyPatchAutoRetryMax}): ${error}\n` +
|
|
195
|
+
`Regenerate a patch that matches the current file contents. ` +
|
|
196
|
+
`For large rewrites, prefer write_file(path, content) or Delete+Add instead of Update.` +
|
|
197
|
+
debugText,
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
};
|
|
201
|
+
if (keepFullTrace)
|
|
202
|
+
fullTraceContents.push(retryInstruction);
|
|
203
|
+
modelContents.push(retryInstruction);
|
|
204
|
+
}
|
|
205
|
+
recordToolEvent({
|
|
206
|
+
toolEvents,
|
|
207
|
+
name,
|
|
208
|
+
effectiveArgs,
|
|
209
|
+
modelArgs,
|
|
210
|
+
readFileMeta,
|
|
211
|
+
toolResult,
|
|
212
|
+
toolResultRaw,
|
|
213
|
+
});
|
|
214
|
+
if (terminalToolNames.includes(name)) {
|
|
215
|
+
return {
|
|
216
|
+
contents: keepFullTrace ? fullTraceContents : modelContents,
|
|
217
|
+
modelContents,
|
|
218
|
+
finalText: "",
|
|
219
|
+
steps: step + 1,
|
|
220
|
+
terminalCall: { name, args: effectiveArgs, response: toolResultRaw },
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
throw new Error(`Tool loop: max steps reached (${maxSteps}).`);
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=toolLoopRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolLoopRunner.js","sourceRoot":"","sources":["../../../src/ai/toolLoop/toolLoopRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport { EVENT_TYPES, EventType } from \"../../types/events.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 ToolHandler = (args: Record<string, unknown>) => Promise<unknown>;\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 handlers: Record<string, ToolHandler>;\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};\n\nexport async function runToolLoop(\n options: RunToolLoopOptions,\n): Promise<ToolLoopResult> {\n const {\n initialContents,\n tools,\n handlers,\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 } = options;\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 fullTraceContents: any[] = keepFullTrace ? [...initialContents] : [];\n let modelContents: any[] = [...initialContents];\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: initialContents.length,\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 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\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 for (const call of functionCalls) {\n const name = call.name?.toString() ?? \"\";\n const args = (call.args ?? {}) as Record<string, unknown>;\n\n if (!name) {\n throw new Error(\"Tool loop: function call missing name.\");\n }\n\n const handler = handlers[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 logger(\n buildToolStatusMessage(name, effectiveArgs, readFileMeta),\n EVENT_TYPES.STEP_STARTED,\n );\n\n const modelArgs = redactFunctionCallArgs(name, effectiveArgs);\n\n const assistantFull = {\n role: \"model\",\n parts: [\n {\n functionCall: {\n name,\n args: effectiveArgs,\n },\n },\n ],\n };\n\n const assistantModel = {\n role: \"model\",\n parts: [\n {\n functionCall: {\n name,\n args: modelArgs,\n },\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 toolResultRaw = await handler(effectiveArgs);\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 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 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 throw new Error(`Tool loop: max steps reached (${maxSteps}).`);\n}\n"]}
|