@empiricalrun/test-gen 0.71.2 → 0.73.0
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/CHANGELOG.md +57 -0
- package/dist/agent/chat/agent-loop.d.ts +11 -9
- package/dist/agent/chat/agent-loop.d.ts.map +1 -1
- package/dist/agent/chat/agent-loop.js +20 -10
- package/dist/agent/chat/exports.d.ts +2 -2
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +6 -1
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +53 -28
- package/dist/agent/chat/prompt/index.d.ts +2 -2
- package/dist/agent/chat/prompt/index.d.ts.map +1 -1
- package/dist/agent/chat/prompt/index.js +5 -4
- package/dist/agent/chat/prompt/repo.d.ts +2 -2
- package/dist/agent/chat/prompt/repo.d.ts.map +1 -1
- package/dist/agent/chat/prompt/repo.js +20 -11
- package/dist/agent/chat/state.d.ts +2 -2
- package/dist/agent/chat/state.d.ts.map +1 -1
- package/dist/agent/chat/types.d.ts +0 -6
- package/dist/agent/chat/types.d.ts.map +1 -1
- package/dist/agent/chat/utils/tool-calls.d.ts +21 -0
- package/dist/agent/chat/utils/tool-calls.d.ts.map +1 -0
- package/dist/agent/chat/utils/tool-calls.js +64 -0
- package/dist/agent/chat/utils.d.ts +2 -4
- package/dist/agent/chat/utils.d.ts.map +1 -1
- package/dist/agent/chat/utils.js +5 -11
- package/dist/agent/code-review/prompt.d.ts +2 -0
- package/dist/agent/code-review/prompt.d.ts.map +1 -0
- package/dist/agent/code-review/prompt.js +19 -0
- package/dist/agent/codegen/create-test-block.d.ts.map +1 -1
- package/dist/agent/codegen/create-test-block.js +0 -10
- package/dist/agent/diagnosis-agent/index.d.ts.map +1 -1
- package/dist/agent/diagnosis-agent/index.js +0 -9
- package/dist/agent/master/browser-tests/index.spec.js +1 -1
- package/dist/agent/master/execute-browser-action.d.ts +1 -1
- package/dist/agent/master/execute-browser-action.d.ts.map +1 -1
- package/dist/agent/master/execute-skill-action.d.ts +1 -1
- package/dist/agent/master/execute-skill-action.d.ts.map +1 -1
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +0 -74
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +18 -6
- package/dist/artifacts/utils.d.ts +2 -2
- package/dist/artifacts/utils.d.ts.map +1 -1
- package/dist/artifacts/utils.js +16 -5
- package/dist/auth/cli-auth.d.ts.map +1 -1
- package/dist/auth/cli-auth.js +3 -7
- package/dist/auth/index.d.ts +1 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -4
- package/dist/auth/token-store.d.ts +1 -1
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +3 -3
- package/dist/bin/environments.d.ts +5 -1
- package/dist/bin/environments.d.ts.map +1 -1
- package/dist/bin/environments.js +76 -44
- package/dist/bin/index.js +33 -74
- package/dist/bin/setup.d.ts +3 -1
- package/dist/bin/setup.d.ts.map +1 -1
- package/dist/bin/setup.js +16 -20
- package/dist/dashboard/client.d.ts +26 -0
- package/dist/dashboard/client.d.ts.map +1 -0
- package/dist/dashboard/client.js +185 -0
- package/dist/dashboard/index.d.ts +3 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +9 -0
- package/dist/dashboard/totp.d.ts +2 -0
- package/dist/dashboard/totp.d.ts.map +1 -0
- package/dist/dashboard/totp.js +14 -0
- package/dist/dashboard/types.d.ts +9 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/types.js +17 -0
- package/dist/file-info/file-system.d.ts +3 -0
- package/dist/file-info/file-system.d.ts.map +1 -0
- package/dist/{utils/file-tree.js → file-info/file-system.js} +2 -8
- package/dist/file-info/github.d.ts +3 -0
- package/dist/file-info/github.d.ts.map +1 -0
- package/dist/file-info/github.js +107 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -9
- package/dist/recorder/env-variables.d.ts.map +1 -1
- package/dist/recorder/env-variables.js +3 -7
- package/dist/recorder/index.js +5 -5
- package/dist/recorder/request.js +4 -9
- package/dist/recorder/upload.d.ts +3 -2
- package/dist/recorder/upload.d.ts.map +1 -1
- package/dist/recorder/upload.js +20 -22
- package/dist/tools/commit-and-create-pr.d.ts.map +1 -1
- package/dist/tools/commit-and-create-pr.js +44 -37
- package/dist/tools/definitions/run-test.d.ts +23 -0
- package/dist/tools/definitions/run-test.d.ts.map +1 -0
- package/dist/tools/definitions/run-test.js +28 -0
- package/dist/tools/definitions/str_replace_editor.d.ts +3 -0
- package/dist/tools/definitions/str_replace_editor.d.ts.map +1 -0
- package/dist/tools/definitions/str_replace_editor.js +74 -0
- package/dist/tools/definitions/test-gen-browser.d.ts +26 -0
- package/dist/tools/definitions/test-gen-browser.d.ts.map +1 -0
- package/dist/tools/definitions/test-gen-browser.js +88 -0
- package/dist/tools/delete-file.d.ts +3 -0
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +83 -0
- package/dist/tools/diagnosis-fetcher.d.ts.map +1 -1
- package/dist/tools/diagnosis-fetcher.js +3 -7
- package/dist/tools/executor/index.d.ts +24 -0
- package/dist/tools/executor/index.d.ts.map +1 -0
- package/dist/{tool-call-service → tools/executor}/index.js +38 -58
- package/dist/tools/executor/utils/checkpoint.d.ts +7 -0
- package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -0
- package/dist/{utils → tools/executor/utils}/checkpoint.js +6 -5
- package/dist/{utils → tools/executor/utils}/git.d.ts +7 -12
- package/dist/tools/executor/utils/git.d.ts.map +1 -0
- package/dist/{utils → tools/executor/utils}/git.js +11 -36
- package/dist/tools/executor/utils/index.d.ts +77 -0
- package/dist/tools/executor/utils/index.d.ts.map +1 -0
- package/dist/tools/executor/utils/index.js +121 -0
- package/dist/tools/executor/utils/pr-description.d.ts +4 -0
- package/dist/tools/executor/utils/pr-description.d.ts.map +1 -0
- package/dist/tools/executor/utils/pr-description.js +24 -0
- package/dist/tools/fetch-image/index.d.ts +3 -0
- package/dist/tools/fetch-image/index.d.ts.map +1 -0
- package/dist/tools/fetch-image/index.js +56 -0
- package/dist/tools/grep/index.d.ts.map +1 -1
- package/dist/tools/grep/index.js +1 -1
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +60 -0
- package/dist/tools/list-environments.d.ts.map +1 -1
- package/dist/tools/list-environments.js +2 -5
- package/dist/tools/merge-conflicts.d.ts +3 -0
- package/dist/tools/merge-conflicts.d.ts.map +1 -0
- package/dist/tools/merge-conflicts.js +107 -0
- package/dist/tools/run-test.d.ts.map +1 -1
- package/dist/tools/run-test.js +4 -25
- package/dist/tools/str_replace_editor.d.ts.map +1 -1
- package/dist/tools/str_replace_editor.js +6 -58
- package/dist/tools/test-gen-browser.d.ts.map +1 -1
- package/dist/tools/test-gen-browser.js +2 -83
- package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
- package/dist/tools/test-run-fetcher/index.js +2 -6
- package/dist/tools/upgrade-packages/index.d.ts.map +1 -1
- package/dist/tools/upgrade-packages/index.js +12 -13
- package/dist/tools/upgrade-packages/utils.d.ts +3 -2
- package/dist/tools/upgrade-packages/utils.d.ts.map +1 -1
- package/dist/tools/upgrade-packages/utils.js +5 -8
- package/dist/tools/utils/queue.d.ts +5 -0
- package/dist/tools/utils/queue.d.ts.map +1 -0
- package/dist/tools/utils/queue.js +41 -0
- package/dist/types/index.d.ts +0 -8
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/SQSClient.d.ts +14 -0
- package/dist/utils/SQSClient.d.ts.map +1 -0
- package/dist/utils/SQSClient.js +116 -0
- package/dist/utils/repo-tree.d.ts +1 -1
- package/dist/utils/repo-tree.d.ts.map +1 -1
- package/dist/utils/repo-tree.js +7 -7
- package/package.json +16 -8
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/auth/api-client.d.ts +0 -13
- package/dist/auth/api-client.d.ts.map +0 -1
- package/dist/auth/api-client.js +0 -103
- package/dist/session/index.d.ts +0 -20
- package/dist/session/index.d.ts.map +0 -1
- package/dist/session/index.js +0 -104
- package/dist/tool-call-service/index.d.ts +0 -32
- package/dist/tool-call-service/index.d.ts.map +0 -1
- package/dist/tool-call-service/utils.d.ts +0 -6
- package/dist/tool-call-service/utils.d.ts.map +0 -1
- package/dist/tool-call-service/utils.js +0 -57
- package/dist/tools/utils/index.d.ts +0 -61
- package/dist/tools/utils/index.d.ts.map +0 -1
- package/dist/tools/utils/index.js +0 -122
- package/dist/utils/checkpoint.d.ts +0 -7
- package/dist/utils/checkpoint.d.ts.map +0 -1
- package/dist/utils/file-tree.d.ts +0 -3
- package/dist/utils/file-tree.d.ts.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"str_replace_editor.d.ts","sourceRoot":"","sources":["../../../src/tools/definitions/str_replace_editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AA0E5D,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAK1D,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.textEditorTools = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const fileViewTool = {
|
|
6
|
+
schema: {
|
|
7
|
+
name: "fileViewTool",
|
|
8
|
+
description: `A tool to view the content of a file or directory. If the path points
|
|
9
|
+
to a directory, the tool will return a list of files in the directory, separated by line breaks.
|
|
10
|
+
If the path points to a file, the tool will return the content of the file.
|
|
11
|
+
|
|
12
|
+
File contents are returned with line numbers, starting from 1.
|
|
13
|
+
|
|
14
|
+
1: line 1
|
|
15
|
+
2: line 2
|
|
16
|
+
...`,
|
|
17
|
+
parameters: zod_1.z.object({
|
|
18
|
+
// Does not support view_range for now
|
|
19
|
+
path: zod_1.z.string().describe("The path to the file or directory to view."),
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
needsBrowser: false,
|
|
23
|
+
};
|
|
24
|
+
const fileCreateTool = {
|
|
25
|
+
schema: {
|
|
26
|
+
name: "fileCreateTool",
|
|
27
|
+
description: `A tool to create a new file with given contents.
|
|
28
|
+
This tool will also create parent directories that do not exist.
|
|
29
|
+
For example, for path "tests/example/foo.spec.ts", the tool will create
|
|
30
|
+
directories "tests", "tests/example", and "tests/example/foo.spec.ts".`,
|
|
31
|
+
parameters: zod_1.z.object({
|
|
32
|
+
path: zod_1.z.string().describe("The path to the new file."),
|
|
33
|
+
file_text: zod_1.z.string().describe("The contents of the new file."),
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
needsBrowser: false,
|
|
37
|
+
};
|
|
38
|
+
const stringReplaceTool = {
|
|
39
|
+
schema: {
|
|
40
|
+
name: "stringReplaceTool",
|
|
41
|
+
description: `A tool to replace a string in a file. This tool requires old_str to be unique
|
|
42
|
+
in the file. If old_str is not unique, the tool will return an error.`,
|
|
43
|
+
parameters: zod_1.z.object({
|
|
44
|
+
path: zod_1.z.string().describe("The path to the file."),
|
|
45
|
+
old_str: zod_1.z.string().describe("The string to be replaced."),
|
|
46
|
+
new_str: zod_1.z.string().describe("The string to replace old_str with."),
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
needsBrowser: false,
|
|
50
|
+
};
|
|
51
|
+
const stringInsertTool = {
|
|
52
|
+
schema: {
|
|
53
|
+
name: "stringInsertTool",
|
|
54
|
+
description: "A tool to insert a string at a specific line in a file. Line numbers are 1-indexed, just like the file view tool.",
|
|
55
|
+
parameters: zod_1.z.object({
|
|
56
|
+
path: zod_1.z.string().describe("The path to the file."),
|
|
57
|
+
insert_line: zod_1.z
|
|
58
|
+
.number()
|
|
59
|
+
.int()
|
|
60
|
+
.min(1)
|
|
61
|
+
.describe(`The line number on which to insert the text (1 for beginning of file).
|
|
62
|
+
To insert a string at the beginning of the file, you should use insert_line = 1.
|
|
63
|
+
To insert a string at the end of the file, you should use insert_line = (total lines + 1).`),
|
|
64
|
+
new_str: zod_1.z.string().describe("The string to insert."),
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
needsBrowser: false,
|
|
68
|
+
};
|
|
69
|
+
exports.textEditorTools = {
|
|
70
|
+
fileViewTool: fileViewTool,
|
|
71
|
+
fileCreateTool: fileCreateTool,
|
|
72
|
+
stringReplaceTool: stringReplaceTool,
|
|
73
|
+
stringInsertTool: stringInsertTool,
|
|
74
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ToolDefinition } from "@empiricalrun/shared-types";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const BrowserAgentSchema: z.ZodObject<{
|
|
4
|
+
testName: z.ZodString;
|
|
5
|
+
testSuites: z.ZodArray<z.ZodString, "many">;
|
|
6
|
+
filePath: z.ZodString;
|
|
7
|
+
project: z.ZodString;
|
|
8
|
+
buildUrl: z.ZodOptional<z.ZodString>;
|
|
9
|
+
changeToMake: z.ZodString;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
testName: string;
|
|
12
|
+
testSuites: string[];
|
|
13
|
+
filePath: string;
|
|
14
|
+
project: string;
|
|
15
|
+
changeToMake: string;
|
|
16
|
+
buildUrl?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
testName: string;
|
|
19
|
+
testSuites: string[];
|
|
20
|
+
filePath: string;
|
|
21
|
+
project: string;
|
|
22
|
+
changeToMake: string;
|
|
23
|
+
buildUrl?: string | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
export declare const generateTestWithBrowserAgent: ToolDefinition;
|
|
26
|
+
//# sourceMappingURL=test-gen-browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../../src/tools/definitions/test-gen-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAwB7B,CAAC;AA4DH,eAAO,MAAM,4BAA4B,EAAE,cAO1C,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTestWithBrowserAgent = exports.BrowserAgentSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
exports.BrowserAgentSchema = zod_1.z.object({
|
|
6
|
+
testName: zod_1.z.string().describe("The name of the test to create or modify"),
|
|
7
|
+
testSuites: zod_1.z
|
|
8
|
+
.array(zod_1.z.string())
|
|
9
|
+
.describe("The suites (describe blocks) where the test is located"),
|
|
10
|
+
filePath: zod_1.z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("Path of the file where the test is located. Path must be relative to the root of the repository. File name must end with .spec.ts. For example: tests/lesson.spec.ts"),
|
|
13
|
+
project: zod_1.z
|
|
14
|
+
.string()
|
|
15
|
+
.describe("The Playwright project to run tests against (e.g. 'chromium' or 'firefox')"),
|
|
16
|
+
buildUrl: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(`The URL of the build to run the test on.
|
|
20
|
+
This is ONLY useful for preview deployments that are dynamically created on every pull request, like Vercel preview deployments.
|
|
21
|
+
For all other cases, the build url does not need to be provided, since it is already hard coded in the test repo.`),
|
|
22
|
+
changeToMake: zod_1.z.string().describe("The change to make to the test"),
|
|
23
|
+
});
|
|
24
|
+
const BROWSER_AGENT_DESCRIPTION = `
|
|
25
|
+
Create or modify a test case with browser agent. The browser agent can take user interactions in a web browser
|
|
26
|
+
and generate Playwright code for that actions. This is a useful tool when the modifications require knowing the
|
|
27
|
+
locator/selector for an element on the page.
|
|
28
|
+
|
|
29
|
+
IMPORTANT: Before you invoke this tool, you need to ensure that the test code is correctly prepared for this
|
|
30
|
+
agent. Preparation involves adding a TODO comment that describes the change that needs to be made, and the page
|
|
31
|
+
variable name where the actions must be performed. The content of the TODO comment calls out the element and browser
|
|
32
|
+
interactions it must take. The TODO comment also has (agent on pageName) next to it, to clearly label that the change
|
|
33
|
+
is for the agent to make on the given page (pageName in this case).
|
|
34
|
+
|
|
35
|
+
To choose the page variable name, go through the test code and find available page variables. If you are replacing some
|
|
36
|
+
existing test code, use the same page variable name as in the existing test code. If you are adding steps to the test,
|
|
37
|
+
use the page variable name that is appropriate for the new steps. The page variable represents the browser page (or tab) that
|
|
38
|
+
the agent is supposed to interact with.
|
|
39
|
+
|
|
40
|
+
For example, this is a good TODO comment:
|
|
41
|
+
|
|
42
|
+
\`\`\`
|
|
43
|
+
test("Example test code", async ({ page }) => {
|
|
44
|
+
await page.goto("https://example.com");
|
|
45
|
+
// TODO(agent on page): Click on the login button
|
|
46
|
+
});
|
|
47
|
+
\`\`\`
|
|
48
|
+
|
|
49
|
+
For the above file, the browser environment will execute the steps before the TODO comment and hand-over the control
|
|
50
|
+
to the browser agent. The agent will do the actions described in the TODO comment and then resume control back to the
|
|
51
|
+
test code.
|
|
52
|
+
|
|
53
|
+
Note that you CANNOT add TODO comments in the middle of a multi-line statement. This will break the tool.
|
|
54
|
+
|
|
55
|
+
For example, this is invalid:
|
|
56
|
+
|
|
57
|
+
\`\`\`
|
|
58
|
+
await extPage
|
|
59
|
+
.getByTestId("virtuoso-item-list")
|
|
60
|
+
// TODO(agent on extPage): Click on the STARS button
|
|
61
|
+
.getByText("STARS", { exact: true })
|
|
62
|
+
.click();
|
|
63
|
+
// This is invalid, because the TODO is in the middle of a multi-line statement
|
|
64
|
+
// Instead, add the TODO before or after the multi-line statement
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
The TODO comment must be inside a test block, not outside of it. For example, this is invalid:
|
|
68
|
+
|
|
69
|
+
\`\`\`
|
|
70
|
+
// --- BEGIN INVALID EXAMPLE ---
|
|
71
|
+
test("Example test code", async ({ page }) => {
|
|
72
|
+
await page.goto("https://example.com");
|
|
73
|
+
});
|
|
74
|
+
// TODO(agent on page): Click on the login button
|
|
75
|
+
// --- END INVALID EXAMPLE ---
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
After execution, the browser agent will return a summary of actions that it took, and the generated Playwright code for them.
|
|
79
|
+
You can then use the text editor tool to replace the TODO comment with the generated Playwright code.
|
|
80
|
+
`;
|
|
81
|
+
exports.generateTestWithBrowserAgent = {
|
|
82
|
+
schema: {
|
|
83
|
+
name: "generateTestWithBrowserAgent",
|
|
84
|
+
description: BROWSER_AGENT_DESCRIPTION,
|
|
85
|
+
parameters: exports.BrowserAgentSchema,
|
|
86
|
+
},
|
|
87
|
+
needsBrowser: true,
|
|
88
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-file.d.ts","sourceRoot":"","sources":["../../src/tools/delete-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAEL,MAAM,4BAA4B,CAAC;AAepC,eAAO,MAAM,cAAc,EAAE,IAwE5B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deleteFileTool = void 0;
|
|
7
|
+
const promises_1 = require("fs/promises");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
const git_1 = require("./executor/utils/git");
|
|
11
|
+
const DeleteFileInputSchema = zod_1.z.object({
|
|
12
|
+
path: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("The path to the file to delete (relative to the repository root). For example, tests/foo.spec.ts"),
|
|
15
|
+
});
|
|
16
|
+
exports.deleteFileTool = {
|
|
17
|
+
schema: {
|
|
18
|
+
name: "deleteFile",
|
|
19
|
+
description: `Delete a file from the filesystem.
|
|
20
|
+
This tool will permanently remove the specified file.
|
|
21
|
+
Use with caution as deleted files cannot be recovered.`,
|
|
22
|
+
parameters: DeleteFileInputSchema,
|
|
23
|
+
},
|
|
24
|
+
needsBrowser: false,
|
|
25
|
+
execute: async ({ input, repoPath, collectArtifacts, }) => {
|
|
26
|
+
try {
|
|
27
|
+
const filePath = path_1.default.join(repoPath, input.path);
|
|
28
|
+
// Validate that the file exists and is actually a file (not a directory)
|
|
29
|
+
try {
|
|
30
|
+
const stats = await (0, promises_1.stat)(filePath);
|
|
31
|
+
if (!stats.isFile()) {
|
|
32
|
+
return {
|
|
33
|
+
isError: true,
|
|
34
|
+
result: `Error: '${input.path}' is not a file. Use a different tool to delete directories.`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
isError: true,
|
|
41
|
+
result: `Error: File '${input.path}' does not exist.`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const resolvedPath = path_1.default.resolve(filePath);
|
|
45
|
+
const resolvedRepoPath = path_1.default.resolve(repoPath);
|
|
46
|
+
if (!resolvedPath.startsWith(resolvedRepoPath)) {
|
|
47
|
+
return {
|
|
48
|
+
isError: true,
|
|
49
|
+
result: `Error: Cannot delete files outside the repository root.`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
await (0, promises_1.unlink)(filePath);
|
|
53
|
+
// Collect git patch artifact after deletion
|
|
54
|
+
if (collectArtifacts) {
|
|
55
|
+
try {
|
|
56
|
+
const gitPatch = (0, git_1.getGitDiff)(input.path, repoPath);
|
|
57
|
+
if (gitPatch.trim()) {
|
|
58
|
+
const patchArtifact = {
|
|
59
|
+
name: `${path_1.default.basename(input.path, path_1.default.extname(input.path))}_delete.patch`,
|
|
60
|
+
contentType: "text/plain",
|
|
61
|
+
data: Buffer.from(gitPatch, "utf-8"),
|
|
62
|
+
};
|
|
63
|
+
collectArtifacts([patchArtifact]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.warn("Failed to create git patch artifact:", error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
isError: false,
|
|
72
|
+
result: `Successfully deleted file: ${input.path}`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error("Error deleting file", error);
|
|
77
|
+
return {
|
|
78
|
+
isError: true,
|
|
79
|
+
result: error instanceof Error ? error.message : String(error),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnosis-fetcher.d.ts","sourceRoot":"","sources":["../../src/tools/diagnosis-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"diagnosis-fetcher.d.ts","sourceRoot":"","sources":["../../src/tools/diagnosis-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAavD,eAAO,MAAM,wBAAwB,EAAE,IAiFtC,CAAC"}
|
|
@@ -7,7 +7,6 @@ exports.fetchDiagnosisReportTool = void 0;
|
|
|
7
7
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const zod_1 = require("zod");
|
|
10
|
-
const utils_1 = require("./utils");
|
|
11
10
|
const DiagnosisSchema = zod_1.z.object({
|
|
12
11
|
diagnosisUrl: zod_1.z
|
|
13
12
|
.string()
|
|
@@ -20,9 +19,7 @@ exports.fetchDiagnosisReportTool = {
|
|
|
20
19
|
parameters: DiagnosisSchema,
|
|
21
20
|
},
|
|
22
21
|
needsBrowser: false,
|
|
23
|
-
execute: async (
|
|
24
|
-
const { input } = params;
|
|
25
|
-
const { repoPath, apiKey } = params;
|
|
22
|
+
execute: async ({ input, repoPath, apiClient }) => {
|
|
26
23
|
const { diagnosisUrl } = input;
|
|
27
24
|
// Extract the slug from the URL - it's the part after the last '--'
|
|
28
25
|
const slug = diagnosisUrl.split("--").pop();
|
|
@@ -34,9 +31,8 @@ exports.fetchDiagnosisReportTool = {
|
|
|
34
31
|
}
|
|
35
32
|
let data = null;
|
|
36
33
|
try {
|
|
37
|
-
data = await
|
|
38
|
-
|
|
39
|
-
apiKey,
|
|
34
|
+
data = await apiClient.request(`/api/diagnosis/${slug}/detailed`, {
|
|
35
|
+
method: "GET",
|
|
40
36
|
});
|
|
41
37
|
}
|
|
42
38
|
catch (error) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TraceClient } from "@empiricalrun/llm";
|
|
2
|
+
import { PendingToolCall, ToolResult } from "@empiricalrun/llm/chat";
|
|
3
|
+
import { ChatSessionInfo, IDashboardAPIClient, ToolExecute } from "@empiricalrun/shared-types";
|
|
4
|
+
export declare class ToolExecutor {
|
|
5
|
+
toolExecutors: Record<string, ToolExecute>;
|
|
6
|
+
chatSession: ChatSessionInfo | null;
|
|
7
|
+
branchName: string;
|
|
8
|
+
repoPath: string;
|
|
9
|
+
apiClient: IDashboardAPIClient;
|
|
10
|
+
trace?: TraceClient;
|
|
11
|
+
featureFlags: string[];
|
|
12
|
+
environmentOverrides: Record<string, string>;
|
|
13
|
+
constructor({ chatSession, branchName, repoPath, apiClient, trace, featureFlags, environmentOverrides, }: {
|
|
14
|
+
chatSession: ChatSessionInfo | null;
|
|
15
|
+
branchName: string;
|
|
16
|
+
repoPath: string;
|
|
17
|
+
apiClient: IDashboardAPIClient;
|
|
18
|
+
trace?: TraceClient;
|
|
19
|
+
featureFlags: string[];
|
|
20
|
+
environmentOverrides?: Record<string, string>;
|
|
21
|
+
});
|
|
22
|
+
execute(toolCalls: PendingToolCall[]): Promise<ToolResult[]>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/executor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAEL,eAAe,EACf,mBAAmB,EACnB,WAAW,EACZ,MAAM,4BAA4B,CAAC;AAqBpC,qBAAa,YAAY;IACvB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAM;IAChD,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAEjC,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAY,EACZ,oBAAyB,GAC1B,EAAE;QACD,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;QACpC,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,mBAAmB,CAAC;QAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;QACpB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC/C;IAkCK,OAAO,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAqEnE"}
|
|
@@ -1,78 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const diagnosis_fetcher_1 = require("../
|
|
8
|
-
const download_build_1 = require("../
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
exports.ToolExecutor = void 0;
|
|
4
|
+
const artifacts_1 = require("../../artifacts");
|
|
5
|
+
const commit_and_create_pr_1 = require("../commit-and-create-pr");
|
|
6
|
+
const delete_file_1 = require("../delete-file");
|
|
7
|
+
const diagnosis_fetcher_1 = require("../diagnosis-fetcher");
|
|
8
|
+
const download_build_1 = require("../download-build");
|
|
9
|
+
const fetch_image_1 = require("../fetch-image");
|
|
10
|
+
const grep_1 = require("../grep");
|
|
11
|
+
const list_environments_1 = require("../list-environments");
|
|
12
|
+
const merge_conflicts_1 = require("../merge-conflicts");
|
|
13
|
+
const run_test_1 = require("../run-test");
|
|
14
|
+
const str_replace_editor_1 = require("../str_replace_editor");
|
|
15
|
+
const test_gen_browser_1 = require("../test-gen-browser");
|
|
16
|
+
const test_run_fetcher_1 = require("../test-run-fetcher");
|
|
17
|
+
const upgrade_packages_1 = require("../upgrade-packages");
|
|
18
|
+
const checkpoint_1 = require("./utils/checkpoint");
|
|
19
|
+
class ToolExecutor {
|
|
20
20
|
toolExecutors = {};
|
|
21
|
-
|
|
22
|
-
selectedModel;
|
|
21
|
+
chatSession;
|
|
23
22
|
branchName;
|
|
24
23
|
repoPath;
|
|
25
|
-
|
|
24
|
+
apiClient;
|
|
26
25
|
trace;
|
|
27
26
|
featureFlags;
|
|
28
27
|
environmentOverrides;
|
|
29
|
-
constructor({
|
|
30
|
-
this.
|
|
31
|
-
this.selectedModel = selectedModel;
|
|
28
|
+
constructor({ chatSession, branchName, repoPath, apiClient, trace, featureFlags, environmentOverrides = {}, }) {
|
|
29
|
+
this.chatSession = chatSession;
|
|
32
30
|
this.branchName = branchName;
|
|
33
31
|
this.trace = trace;
|
|
34
32
|
this.repoPath = repoPath;
|
|
35
|
-
this.
|
|
33
|
+
this.apiClient = apiClient;
|
|
36
34
|
this.featureFlags = featureFlags;
|
|
37
35
|
this.environmentOverrides = environmentOverrides;
|
|
38
|
-
|
|
36
|
+
const tools = [
|
|
39
37
|
grep_1.grepTool,
|
|
40
38
|
run_test_1.runTestTool,
|
|
41
39
|
test_run_fetcher_1.fetchTestRunReportTool,
|
|
42
40
|
diagnosis_fetcher_1.fetchDiagnosisReportTool,
|
|
43
41
|
test_gen_browser_1.generateTestWithBrowserAgent,
|
|
44
42
|
commit_and_create_pr_1.createPullRequestTool,
|
|
43
|
+
merge_conflicts_1.mergeConflictsTool,
|
|
45
44
|
list_environments_1.listEnvironmentsTool,
|
|
46
45
|
download_build_1.downloadBuildTool,
|
|
47
46
|
upgrade_packages_1.upgradePackagesTool,
|
|
47
|
+
fetch_image_1.fetchImageTool,
|
|
48
|
+
delete_file_1.deleteFileTool,
|
|
49
|
+
...str_replace_editor_1.textEditorTools,
|
|
48
50
|
];
|
|
49
|
-
|
|
50
|
-
this.tools.push(...str_replace_editor_1.textEditorTools);
|
|
51
|
-
}
|
|
52
|
-
this.tools.forEach((tool) => {
|
|
51
|
+
tools.forEach((tool) => {
|
|
53
52
|
this.toolExecutors[tool.schema.name] = tool.execute;
|
|
54
53
|
});
|
|
55
|
-
|
|
56
|
-
this.toolExecutors
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
async sendToQueue(requestId, toolCalls) {
|
|
65
|
-
const queueUrl = (0, utils_1.getQueueUrl)(toolCalls, this.tools);
|
|
66
|
-
if (!queueUrl) {
|
|
67
|
-
throw new Error(`queueUrl is required for remote execution.`);
|
|
68
|
-
}
|
|
69
|
-
await (0, utils_1.sendToolRequestToRemoteQueue)(queueUrl, {
|
|
70
|
-
toolCalls,
|
|
71
|
-
requestId,
|
|
72
|
-
chatSessionId: this.chatSessionId,
|
|
73
|
-
selectedModel: this.selectedModel,
|
|
74
|
-
branchName: this.branchName,
|
|
75
|
-
});
|
|
54
|
+
this.toolExecutors = {
|
|
55
|
+
...this.toolExecutors,
|
|
56
|
+
// Support for Claude 3x and 4: They use different tool names
|
|
57
|
+
str_replace_editor: str_replace_editor_1.strReplaceEditorExecutor,
|
|
58
|
+
str_replace_based_edit_tool: str_replace_editor_1.strReplaceEditorExecutor,
|
|
59
|
+
};
|
|
76
60
|
}
|
|
77
61
|
async execute(toolCalls) {
|
|
78
62
|
const executeSpan = this.trace?.span({
|
|
@@ -90,7 +74,6 @@ class ToolCallService {
|
|
|
90
74
|
uploadArtifactsQueue.addTask(artifactsInput).catch((error) => {
|
|
91
75
|
console.error("Error collecting artifacts:", error);
|
|
92
76
|
});
|
|
93
|
-
return;
|
|
94
77
|
};
|
|
95
78
|
const toolExecutor = this.toolExecutors[toolCall.name];
|
|
96
79
|
if (!toolExecutor) {
|
|
@@ -103,16 +86,13 @@ class ToolCallService {
|
|
|
103
86
|
span?.end({ output: errorResult });
|
|
104
87
|
continue;
|
|
105
88
|
}
|
|
106
|
-
if (!this.apiKey) {
|
|
107
|
-
throw new Error("API key is required for tool execution");
|
|
108
|
-
}
|
|
109
89
|
try {
|
|
110
90
|
const result = await toolExecutor({
|
|
111
91
|
input: toolCall.input,
|
|
112
92
|
repoPath: this.repoPath,
|
|
113
|
-
|
|
93
|
+
apiClient: this.apiClient,
|
|
114
94
|
trace: this.trace,
|
|
115
|
-
|
|
95
|
+
chatSession: this.chatSession,
|
|
116
96
|
collectArtifacts: collectArtifactsFn,
|
|
117
97
|
environmentOverrides: this.environmentOverrides,
|
|
118
98
|
featureFlags: this.featureFlags,
|
|
@@ -131,7 +111,7 @@ class ToolCallService {
|
|
|
131
111
|
span?.end({ output: errorResult });
|
|
132
112
|
}
|
|
133
113
|
}
|
|
134
|
-
|
|
114
|
+
(0, checkpoint_1.createCommitCheckpoint)({
|
|
135
115
|
toolCalls,
|
|
136
116
|
branchName: this.branchName,
|
|
137
117
|
repoPath: this.repoPath,
|
|
@@ -140,4 +120,4 @@ class ToolCallService {
|
|
|
140
120
|
return toolResults;
|
|
141
121
|
}
|
|
142
122
|
}
|
|
143
|
-
exports.
|
|
123
|
+
exports.ToolExecutor = ToolExecutor;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PendingToolCall } from "@empiricalrun/llm/chat";
|
|
2
|
+
export declare function createCommitCheckpoint({ toolCalls, branchName, repoPath, }: {
|
|
3
|
+
toolCalls: PendingToolCall[];
|
|
4
|
+
branchName: string;
|
|
5
|
+
repoPath: string;
|
|
6
|
+
}): void;
|
|
7
|
+
//# sourceMappingURL=checkpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../../../../src/tools/executor/utils/checkpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAKzD,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,UAAU,EACV,QAAQ,GACT,EAAE;IACD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,QA0BA"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createCommitCheckpoint = createCommitCheckpoint;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
4
5
|
const git_1 = require("./git");
|
|
5
|
-
|
|
6
|
-
const filesChanged =
|
|
6
|
+
function createCommitCheckpoint({ toolCalls, branchName, repoPath, }) {
|
|
7
|
+
const filesChanged = (0, git_1.getFilesChanged)(repoPath);
|
|
7
8
|
const toolsWithUpdatedFiles = toolCalls
|
|
8
9
|
.filter((tc) => "path" in tc.input &&
|
|
9
10
|
tc.input.path &&
|
|
@@ -15,11 +16,11 @@ async function createCheckpoint({ toolCalls, branchName, repoPath, }) {
|
|
|
15
16
|
const filesToCommit = toolsWithUpdatedFiles.map((tool) => tool.path);
|
|
16
17
|
if (toolsWithUpdatedFiles.length > 0) {
|
|
17
18
|
let commitMessage = `${toolsWithUpdatedFiles.map((tool) => `${tool.name} on ${tool.path}`).join(", ")}`;
|
|
18
|
-
|
|
19
|
+
(0, git_1.commitFilesAsBotUser)({
|
|
19
20
|
commitMessage,
|
|
20
|
-
branchName,
|
|
21
21
|
files: filesToCommit,
|
|
22
22
|
repoPath,
|
|
23
23
|
});
|
|
24
|
+
(0, child_process_1.execSync)(`git push origin ${branchName}`, { cwd: repoPath });
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -1,24 +1,19 @@
|
|
|
1
|
+
import { IDashboardAPIClient } from "@empiricalrun/shared-types";
|
|
1
2
|
export declare function getGitDiff(filepath: string, cwd: string): string;
|
|
2
3
|
export declare function getGitDiffForNewFile(filepath: string, cwd: string): string;
|
|
3
4
|
export declare function checkoutBranch(branchName: string, cwd: string): Promise<void>;
|
|
4
|
-
export declare function commitAsBotUser(commitMessage: string, cwd: string):
|
|
5
|
+
export declare function commitAsBotUser(commitMessage: string, cwd: string): boolean;
|
|
5
6
|
export declare function getCurrentBranchName(repoPath: string): Promise<string>;
|
|
6
7
|
export declare function pullBranch(branchName: string, cwd: string): Promise<void>;
|
|
7
|
-
export declare function
|
|
8
|
+
export declare function commitFilesAsBotUser({ commitMessage, files, repoPath, }: {
|
|
8
9
|
commitMessage: string;
|
|
9
|
-
branchName: string;
|
|
10
10
|
files: string[];
|
|
11
11
|
repoPath: string;
|
|
12
|
-
}):
|
|
13
|
-
export declare function getFilesChanged(cwd: string):
|
|
14
|
-
export declare function mergePullRequest({ repoName, prNumber,
|
|
12
|
+
}): void;
|
|
13
|
+
export declare function getFilesChanged(cwd: string): string[];
|
|
14
|
+
export declare function mergePullRequest({ repoName, prNumber, apiClient, }: {
|
|
15
15
|
repoName: string;
|
|
16
16
|
prNumber: number;
|
|
17
|
-
|
|
17
|
+
apiClient: IDashboardAPIClient;
|
|
18
18
|
}): Promise<boolean>;
|
|
19
|
-
export declare function deleteBranch({ repoName, branchName, apiKey, }: {
|
|
20
|
-
repoName: string;
|
|
21
|
-
branchName: string;
|
|
22
|
-
apiKey: string;
|
|
23
|
-
}): Promise<void>;
|
|
24
19
|
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../../src/tools/executor/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAe1E;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,iBAMnE;AAED,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,WAcjE;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,mBAO1D;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,iBAE/D;AAED,wBAAgB,oBAAoB,CAAC,EACnC,aAAa,EACb,KAAK,EACL,QAAQ,GACT,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,QAGA;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,YAU1C;AAED,wBAAsB,gBAAgB,CAAC,EACrC,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,mBAAmB,CAAC;CAChC,oBA8BA"}
|