@empiricalrun/test-gen 0.75.0 → 0.77.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 +48 -0
- package/dist/agent/base/index.d.ts +32 -21
- package/dist/agent/base/index.d.ts.map +1 -1
- package/dist/agent/base/index.js +100 -57
- package/dist/agent/browsing/run.d.ts +1 -2
- package/dist/agent/browsing/run.d.ts.map +1 -1
- package/dist/agent/browsing/run.js +3 -9
- package/dist/agent/browsing/utils.d.ts +2 -9
- package/dist/agent/browsing/utils.d.ts.map +1 -1
- package/dist/agent/browsing/utils.js +5 -109
- package/dist/agent/chat/agent-loop.d.ts +8 -7
- package/dist/agent/chat/agent-loop.d.ts.map +1 -1
- package/dist/agent/chat/agent-loop.js +7 -18
- package/dist/agent/chat/exports.d.ts +9 -6
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +11 -13
- package/dist/agent/chat/index.d.ts +6 -10
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +117 -196
- package/dist/agent/chat/models.d.ts +0 -2
- package/dist/agent/chat/models.d.ts.map +1 -1
- package/dist/agent/chat/models.js +12 -26
- package/dist/agent/chat/prompt/pw-utils-docs.d.ts +1 -1
- package/dist/agent/chat/prompt/pw-utils-docs.d.ts.map +1 -1
- package/dist/agent/chat/prompt/pw-utils-docs.js +52 -0
- package/dist/agent/chat/prompt/repo.d.ts.map +1 -1
- package/dist/agent/chat/prompt/repo.js +11 -22
- package/dist/agent/chat/prompt/test-case-def.d.ts +2 -0
- package/dist/agent/chat/prompt/test-case-def.d.ts.map +1 -0
- package/dist/agent/chat/prompt/test-case-def.js +44 -0
- package/dist/agent/chat/state.d.ts +8 -8
- package/dist/agent/chat/state.d.ts.map +1 -1
- package/dist/agent/chat/state.js +17 -47
- package/dist/agent/chat/utils.d.ts +4 -5
- package/dist/agent/chat/utils.d.ts.map +1 -1
- package/dist/agent/chat/utils.js +15 -9
- package/dist/agent/cli.d.ts +11 -0
- package/dist/agent/cli.d.ts.map +1 -0
- package/dist/agent/cli.js +213 -0
- package/dist/agent/code-review/executor/index.d.ts +5 -0
- package/dist/agent/code-review/executor/index.d.ts.map +1 -0
- package/dist/agent/code-review/executor/index.js +13 -0
- package/dist/agent/code-review/index.d.ts +12 -0
- package/dist/agent/code-review/index.d.ts.map +1 -0
- package/dist/agent/code-review/index.js +159 -0
- package/dist/agent/code-review/parser.d.ts +5 -0
- package/dist/agent/code-review/parser.d.ts.map +1 -0
- package/dist/agent/code-review/parser.js +70 -0
- package/dist/agent/code-review/types.d.ts +36 -0
- package/dist/agent/code-review/types.d.ts.map +1 -0
- package/dist/agent/code-review/types.js +13 -0
- package/dist/agent/cua/index.d.ts.map +1 -1
- package/dist/agent/cua/index.js +18 -2
- package/dist/agent/cua/model.d.ts.map +1 -1
- package/dist/agent/cua/model.js +4 -1
- package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +19 -0
- package/dist/agent/triage/index.d.ts +7 -0
- package/dist/agent/triage/index.d.ts.map +1 -0
- package/dist/agent/triage/index.js +103 -0
- package/dist/agent/video-analysis/executor/index.d.ts +5 -0
- package/dist/agent/video-analysis/executor/index.d.ts.map +1 -0
- package/dist/agent/video-analysis/executor/index.js +10 -0
- package/dist/agent/video-analysis/index.d.ts +7 -0
- package/dist/agent/video-analysis/index.d.ts.map +1 -0
- package/dist/agent/video-analysis/index.js +60 -0
- package/dist/artifacts/index.d.ts +1 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +3 -1
- package/dist/artifacts/utils.d.ts.map +1 -1
- package/dist/bin/index.js +68 -23
- package/dist/constants/index.d.ts +14 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +33 -1
- package/dist/file/server.d.ts +1 -3
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +0 -13
- package/dist/file-info/adapters/file-system/index.d.ts.map +1 -1
- package/dist/file-info/adapters/file-system/reader.d.ts.map +1 -1
- package/dist/file-info/adapters/file-system/reader.js +8 -1
- package/dist/file-info/adapters/github/index.d.ts.map +1 -1
- package/dist/file-info/adapters/github/index.js +1 -2
- package/dist/file-info/adapters/github/reader.d.ts +4 -9
- package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
- package/dist/file-info/adapters/github/reader.js +166 -134
- package/dist/index.d.ts.map +1 -1
- package/dist/tools/analyse-video/index.d.ts +5 -0
- package/dist/tools/analyse-video/index.d.ts.map +1 -0
- package/dist/tools/analyse-video/index.js +50 -0
- package/dist/tools/create-pull-request/index.d.ts.map +1 -0
- package/dist/tools/{definitions/commit-and-create-pr.js → create-pull-request/index.js} +28 -1
- package/dist/tools/create-pull-request/utils.d.ts +21 -0
- package/dist/tools/create-pull-request/utils.d.ts.map +1 -0
- package/dist/tools/create-pull-request/utils.js +83 -0
- package/dist/tools/definitions/{fetch-video-analysis.d.ts → analyse-video.d.ts} +17 -12
- package/dist/tools/definitions/analyse-video.d.ts.map +1 -0
- package/dist/tools/definitions/analyse-video.js +60 -0
- package/dist/tools/definitions/review-pull-request.d.ts +3 -0
- package/dist/tools/definitions/review-pull-request.d.ts.map +1 -0
- package/dist/tools/definitions/review-pull-request.js +16 -0
- package/dist/tools/definitions/str_replace_editor.d.ts +1 -0
- package/dist/tools/definitions/str_replace_editor.d.ts.map +1 -1
- package/dist/tools/definitions/str_replace_editor.js +4 -1
- package/dist/tools/definitions/test-gen-browser.d.ts +0 -3
- package/dist/tools/definitions/test-gen-browser.d.ts.map +1 -1
- package/dist/tools/definitions/test-gen-browser.js +33 -8
- package/dist/tools/delete-file/index.d.ts.map +1 -1
- package/dist/tools/delete-file/index.js +1 -19
- package/dist/tools/executor/base.d.ts +32 -0
- package/dist/tools/executor/base.d.ts.map +1 -0
- package/dist/tools/executor/base.js +114 -0
- package/dist/tools/executor/index.d.ts +3 -22
- package/dist/tools/executor/index.d.ts.map +1 -1
- package/dist/tools/executor/index.js +13 -92
- package/dist/tools/executor/utils/checkpoint.d.ts +1 -1
- package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -1
- package/dist/tools/executor/utils/checkpoint.js +6 -2
- package/dist/tools/executor/utils/git.d.ts +2 -2
- package/dist/tools/executor/utils/git.d.ts.map +1 -1
- package/dist/tools/executor/utils/git.js +7 -3
- package/dist/tools/executor/utils/index.d.ts.map +1 -1
- package/dist/tools/executor/utils/index.js +1 -1
- package/dist/tools/fetch-session-diff/index.d.ts +3 -0
- package/dist/tools/fetch-session-diff/index.d.ts.map +1 -0
- package/dist/tools/fetch-session-diff/index.js +46 -0
- package/dist/tools/file-operations/create.d.ts.map +1 -1
- package/dist/tools/file-operations/create.js +1 -4
- package/dist/tools/file-operations/index.d.ts +2 -1
- package/dist/tools/file-operations/index.d.ts.map +1 -1
- package/dist/tools/file-operations/index.js +4 -1
- package/dist/tools/file-operations/insert.d.ts +1 -2
- package/dist/tools/file-operations/insert.d.ts.map +1 -1
- package/dist/tools/file-operations/insert.js +1 -4
- package/dist/tools/file-operations/replace.d.ts.map +1 -1
- package/dist/tools/file-operations/replace.js +1 -4
- package/dist/tools/grep/index.d.ts.map +1 -1
- package/dist/tools/grep/index.js +18 -11
- package/dist/tools/index.d.ts +28 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +52 -33
- package/dist/tools/merge-conflicts/index.d.ts.map +1 -1
- package/dist/tools/merge-conflicts/index.js +1 -1
- package/dist/tools/rename-file/index.js +1 -1
- package/dist/tools/review-pull-request/index.d.ts +3 -0
- package/dist/tools/review-pull-request/index.d.ts.map +1 -0
- package/dist/tools/review-pull-request/index.js +89 -0
- package/dist/tools/run-test.d.ts.map +1 -1
- package/dist/tools/run-test.js +25 -3
- package/dist/tools/test-gen-browser.d.ts.map +1 -1
- package/dist/tools/test-gen-browser.js +51 -47
- package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
- package/dist/tools/test-run-fetcher/index.js +4 -14
- package/dist/tools/utils/urls.d.ts +5 -0
- package/dist/tools/utils/urls.d.ts.map +1 -0
- package/dist/tools/utils/urls.js +19 -0
- package/dist/tools/view-failed-test-run-report/index.d.ts.map +1 -1
- package/dist/tools/view-failed-test-run-report/index.js +3 -15
- package/dist/utils/artifact-paths.d.ts +20 -0
- package/dist/utils/artifact-paths.d.ts.map +1 -0
- package/dist/utils/artifact-paths.js +16 -0
- package/dist/utils/dedup-image-fs.d.ts +2 -16
- package/dist/utils/dedup-image-fs.d.ts.map +1 -1
- package/dist/utils/dedup-image-fs.js +12 -16
- package/dist/utils/dedup-image.d.ts +1 -14
- package/dist/utils/dedup-image.d.ts.map +1 -1
- package/dist/utils/dedup-image.js +7 -62
- package/dist/{tools/fetch-video-analysis/local-ffmpeg-client.d.ts → utils/ffmpeg/index.d.ts} +9 -6
- package/dist/utils/ffmpeg/index.d.ts.map +1 -0
- package/dist/utils/ffmpeg/index.js +415 -0
- package/dist/utils/file.d.ts +1 -0
- package/dist/utils/file.d.ts.map +1 -1
- package/dist/utils/file.js +45 -1
- package/dist/utils/find-threshold.d.ts +8 -0
- package/dist/utils/find-threshold.d.ts.map +1 -0
- package/dist/utils/find-threshold.js +55 -0
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +24 -0
- package/dist/utils/model.d.ts +1 -1
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +7 -5
- package/dist/utils/repo-tree.d.ts +0 -1
- package/dist/utils/repo-tree.d.ts.map +1 -1
- package/dist/utils/repo-tree.js +2 -14
- package/dist/utils/slug.js +1 -1
- package/dist/video-core/agent-orchestrator.d.ts +14 -0
- package/dist/video-core/agent-orchestrator.d.ts.map +1 -0
- package/dist/video-core/agent-orchestrator.js +78 -0
- package/dist/video-core/analysis-server.d.ts +24 -0
- package/dist/video-core/analysis-server.d.ts.map +1 -0
- package/dist/video-core/analysis-server.js +398 -0
- package/dist/video-core/analysis-viewer.html +1374 -0
- package/dist/video-core/index.d.ts +44 -0
- package/dist/video-core/index.d.ts.map +1 -0
- package/dist/video-core/index.js +204 -0
- package/dist/video-core/model-limits.d.ts +4 -0
- package/dist/video-core/model-limits.d.ts.map +1 -0
- package/dist/video-core/model-limits.js +67 -0
- package/dist/video-core/storage-manager.d.ts +5 -0
- package/dist/video-core/storage-manager.d.ts.map +1 -0
- package/dist/video-core/storage-manager.js +55 -0
- package/dist/video-core/types.d.ts +13 -0
- package/dist/video-core/types.d.ts.map +1 -0
- package/dist/video-core/types.js +2 -0
- package/dist/video-core/utils.d.ts +25 -0
- package/dist/video-core/utils.d.ts.map +1 -0
- package/dist/video-core/utils.js +211 -0
- package/dist/video-core/xml-parser.d.ts +3 -0
- package/dist/video-core/xml-parser.d.ts.map +1 -0
- package/dist/video-core/xml-parser.js +27 -0
- package/package.json +5 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/agent/chat/prompt/index.d.ts +0 -5
- package/dist/agent/chat/prompt/index.d.ts.map +0 -1
- package/dist/agent/chat/prompt/index.js +0 -189
- package/dist/agent/chat/utils/tool-calls.d.ts +0 -21
- package/dist/agent/chat/utils/tool-calls.d.ts.map +0 -1
- package/dist/agent/chat/utils/tool-calls.js +0 -64
- package/dist/agent/code-review/prompt.d.ts +0 -2
- package/dist/agent/code-review/prompt.d.ts.map +0 -1
- package/dist/agent/code-review/prompt.js +0 -19
- package/dist/agent/diagnosis-agent/index.d.ts +0 -11
- package/dist/agent/diagnosis-agent/index.d.ts.map +0 -1
- package/dist/agent/diagnosis-agent/index.js +0 -88
- package/dist/agent/diagnosis-agent/strict-mode-violation.d.ts +0 -10
- package/dist/agent/diagnosis-agent/strict-mode-violation.d.ts.map +0 -1
- package/dist/agent/diagnosis-agent/strict-mode-violation.js +0 -30
- package/dist/tools/commit-and-create-pr/index.d.ts.map +0 -1
- package/dist/tools/commit-and-create-pr/index.js +0 -83
- package/dist/tools/definitions/commit-and-create-pr.d.ts +0 -3
- package/dist/tools/definitions/commit-and-create-pr.d.ts.map +0 -1
- package/dist/tools/definitions/fetch-video-analysis.d.ts.map +0 -1
- package/dist/tools/definitions/fetch-video-analysis.js +0 -61
- package/dist/tools/fetch-video-analysis/index.d.ts +0 -5
- package/dist/tools/fetch-video-analysis/index.d.ts.map +0 -1
- package/dist/tools/fetch-video-analysis/index.js +0 -138
- package/dist/tools/fetch-video-analysis/local-ffmpeg-client.d.ts.map +0 -1
- package/dist/tools/fetch-video-analysis/local-ffmpeg-client.js +0 -247
- package/dist/tools/fetch-video-analysis/open-ai.d.ts +0 -6
- package/dist/tools/fetch-video-analysis/open-ai.d.ts.map +0 -1
- package/dist/tools/fetch-video-analysis/open-ai.js +0 -37
- package/dist/tools/fetch-video-analysis/utils.d.ts +0 -13
- package/dist/tools/fetch-video-analysis/utils.d.ts.map +0 -1
- package/dist/tools/fetch-video-analysis/utils.js +0 -98
- package/dist/tools/fetch-video-analysis/video-analysis.d.ts +0 -7
- package/dist/tools/fetch-video-analysis/video-analysis.d.ts.map +0 -1
- package/dist/tools/fetch-video-analysis/video-analysis.js +0 -54
- package/dist/tools/file-operations/shared/git-helper.d.ts +0 -4
- package/dist/tools/file-operations/shared/git-helper.d.ts.map +0 -1
- package/dist/tools/file-operations/shared/git-helper.js +0 -29
- package/eslint.config.mjs +0 -43
- /package/dist/tools/{commit-and-create-pr → create-pull-request}/index.d.ts +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reviewPullRequestTool = void 0;
|
|
4
|
+
const state_1 = require("../../agent/chat/state");
|
|
5
|
+
const code_review_1 = require("../../agent/code-review");
|
|
6
|
+
const executor_1 = require("../../agent/code-review/executor");
|
|
7
|
+
const review_pull_request_1 = require("../definitions/review-pull-request");
|
|
8
|
+
const CODE_REVIEW_MODEL = "claude-sonnet-4-20250514";
|
|
9
|
+
exports.reviewPullRequestTool = {
|
|
10
|
+
...review_pull_request_1.reviewPullRequestTool,
|
|
11
|
+
execute: async ({ input, apiClient, chatSession, environmentOverrides, trace, featureFlags, repoPath, }) => {
|
|
12
|
+
try {
|
|
13
|
+
const { sessionUrl } = input;
|
|
14
|
+
if (!sessionUrl) {
|
|
15
|
+
return {
|
|
16
|
+
isError: true,
|
|
17
|
+
result: "No chat session URL provided",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (!apiClient)
|
|
21
|
+
return {
|
|
22
|
+
isError: true,
|
|
23
|
+
result: "API Client not available",
|
|
24
|
+
};
|
|
25
|
+
// creating chat state to pass to model
|
|
26
|
+
const userPrompt = `Review this session: ${sessionUrl}`;
|
|
27
|
+
const chatState = (0, state_1.createChatState)({
|
|
28
|
+
userPrompt,
|
|
29
|
+
attachments: [],
|
|
30
|
+
existingState: undefined,
|
|
31
|
+
selectedModel: CODE_REVIEW_MODEL,
|
|
32
|
+
error: null,
|
|
33
|
+
});
|
|
34
|
+
const span = trace?.span({
|
|
35
|
+
name: "code-review-agent",
|
|
36
|
+
input: {
|
|
37
|
+
sessionUrl,
|
|
38
|
+
model: CODE_REVIEW_MODEL,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const codeReviewToolExecutor = new executor_1.CodeReviewToolExecutor({
|
|
42
|
+
chatSession: chatSession || null,
|
|
43
|
+
repoPath,
|
|
44
|
+
apiClient,
|
|
45
|
+
trace: span,
|
|
46
|
+
featureFlags,
|
|
47
|
+
environmentOverrides: environmentOverrides || {},
|
|
48
|
+
});
|
|
49
|
+
const agentParams = {
|
|
50
|
+
featureFlags: [],
|
|
51
|
+
selectedModel: CODE_REVIEW_MODEL,
|
|
52
|
+
chatState,
|
|
53
|
+
toolExecutor: codeReviewToolExecutor,
|
|
54
|
+
trace: span,
|
|
55
|
+
};
|
|
56
|
+
const agent = new code_review_1.CodeReviewAgent({ ...agentParams });
|
|
57
|
+
while (!agent.askUserForInput) {
|
|
58
|
+
await agent.runLoop({
|
|
59
|
+
reporter: async () => { },
|
|
60
|
+
trace: span,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const agentResult = agent.getResult();
|
|
64
|
+
span?.end({
|
|
65
|
+
output: {
|
|
66
|
+
result: agentResult,
|
|
67
|
+
success: !!agentResult,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
if (!agentResult) {
|
|
71
|
+
return {
|
|
72
|
+
isError: true,
|
|
73
|
+
result: "Could not extract text response from agent",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
isError: false,
|
|
78
|
+
result: JSON.stringify(agentResult),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error("Error reviewing pull request", error);
|
|
83
|
+
return {
|
|
84
|
+
isError: true,
|
|
85
|
+
result: error instanceof Error ? error.message : String(error),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-test.d.ts","sourceRoot":"","sources":["../../src/tools/run-test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"run-test.d.ts","sourceRoot":"","sources":["../../src/tools/run-test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,IAAI,EAAc,MAAM,4BAA4B,CAAC;AA0C3E,eAAO,MAAM,WAAW,EAAE,IA4GzB,CAAC"}
|
package/dist/tools/run-test.js
CHANGED
|
@@ -29,7 +29,7 @@ ${JSON.stringify(truncatedSummaryJson)}
|
|
|
29
29
|
}
|
|
30
30
|
exports.runTestTool = {
|
|
31
31
|
...run_test_1.runTestTool,
|
|
32
|
-
execute: async ({ input, repoPath, collectArtifacts, environmentOverrides = {}, }) => {
|
|
32
|
+
execute: async ({ input, repoPath, collectArtifacts, environmentOverrides = {}, logger, }) => {
|
|
33
33
|
let reportUrl = undefined;
|
|
34
34
|
let envOverrides = { ...environmentOverrides };
|
|
35
35
|
if ((0, artifacts_1.isArtifactCollectionEnabled)()) {
|
|
@@ -43,14 +43,18 @@ exports.runTestTool = {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
|
-
|
|
46
|
+
const warnMsg = "R2 credentials not found: report artifacts will not be uploaded";
|
|
47
|
+
logger?.warn(warnMsg) || console.warn(warnMsg);
|
|
47
48
|
}
|
|
48
49
|
const { filePath } = input;
|
|
49
50
|
const absoluteFilePath = path_1.default.join(repoPath, filePath);
|
|
50
51
|
if (!fs_1.default.existsSync(absoluteFilePath)) {
|
|
52
|
+
const errorMsg = `File ${filePath} does not exist.`;
|
|
53
|
+
logger?.error("Test file not found", { filePath, absoluteFilePath }) ||
|
|
54
|
+
console.error("Test file not found:", filePath);
|
|
51
55
|
return {
|
|
52
56
|
isError: true,
|
|
53
|
-
result:
|
|
57
|
+
result: errorMsg,
|
|
54
58
|
};
|
|
55
59
|
}
|
|
56
60
|
if (input.buildUrl) {
|
|
@@ -60,6 +64,12 @@ exports.runTestTool = {
|
|
|
60
64
|
};
|
|
61
65
|
}
|
|
62
66
|
try {
|
|
67
|
+
logger?.info("Starting test execution", {
|
|
68
|
+
testName: input.testName,
|
|
69
|
+
filePath,
|
|
70
|
+
project: input.project,
|
|
71
|
+
suites: input.suites,
|
|
72
|
+
}) || console.log("Starting test execution:", input.testName);
|
|
63
73
|
const result = await (0, test_run_1.runSingleTest)({
|
|
64
74
|
testName: input.testName,
|
|
65
75
|
suites: input.suites,
|
|
@@ -67,7 +77,14 @@ exports.runTestTool = {
|
|
|
67
77
|
repoDir: repoPath,
|
|
68
78
|
projects: [input.project],
|
|
69
79
|
envOverrides,
|
|
80
|
+
stdout: logger?.createPrefixedStream?.("stdout"),
|
|
81
|
+
stderr: logger?.createPrefixedStream?.("stderr"),
|
|
70
82
|
});
|
|
83
|
+
logger?.info("Test execution completed", {
|
|
84
|
+
passed: result.hasTestPassed,
|
|
85
|
+
testCount: result.summaryJson?.suites?.length || 0,
|
|
86
|
+
}) ||
|
|
87
|
+
console.log("Test execution completed. Passed:", result.hasTestPassed);
|
|
71
88
|
const artifacts = (0, utils_1.extractAttachmentsFromPlaywrightJSONReport)(result.summaryJson);
|
|
72
89
|
void collectArtifacts?.(artifacts);
|
|
73
90
|
return {
|
|
@@ -82,6 +99,11 @@ exports.runTestTool = {
|
|
|
82
99
|
catch (error) {
|
|
83
100
|
// Ensure we capture the full error message regardless of error type
|
|
84
101
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
102
|
+
logger?.error("Test execution failed", {
|
|
103
|
+
error: errorMessage,
|
|
104
|
+
testName: input.testName,
|
|
105
|
+
filePath,
|
|
106
|
+
}) || console.error("Test execution failed:", errorMessage);
|
|
85
107
|
return {
|
|
86
108
|
artifacts: null,
|
|
87
109
|
result: JSON.stringify({ error: errorMessage }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAqBtE,eAAO,MAAM,4BAA4B,EAAE,IA+L1C,CAAC"}
|
|
@@ -10,6 +10,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const run_1 = require("../agent/browsing/run");
|
|
11
11
|
const utils_1 = require("../agent/browsing/utils");
|
|
12
12
|
const pw_pause_1 = require("../agent/cua/pw-codegen/pw-pause");
|
|
13
|
+
const utils_2 = require("../artifacts/utils");
|
|
13
14
|
const web_1 = require("../bin/utils/platform/web");
|
|
14
15
|
const scenarios_1 = require("../bin/utils/scenarios");
|
|
15
16
|
const test_gen_browser_1 = require("./definitions/test-gen-browser");
|
|
@@ -53,8 +54,9 @@ exports.generateTestWithBrowserAgent = {
|
|
|
53
54
|
}
|
|
54
55
|
// Prepare the file for the browser agent
|
|
55
56
|
const fileBackup = fs_1.default.readFileSync(absoluteFilePath, "utf-8");
|
|
57
|
+
let todoContent;
|
|
56
58
|
try {
|
|
57
|
-
|
|
59
|
+
todoContent = (0, utils_1.replaceTodoWithCreateTest)(filePath, repoPath);
|
|
58
60
|
}
|
|
59
61
|
catch (error) {
|
|
60
62
|
// Undo the TODO -> createTest and test.only changes
|
|
@@ -83,7 +85,7 @@ exports.generateTestWithBrowserAgent = {
|
|
|
83
85
|
BUILD_URL: input.buildUrl,
|
|
84
86
|
};
|
|
85
87
|
}
|
|
86
|
-
const testGenToken = (0, scenarios_1.buildTokenFromOptions)({ name: testName, file: filePath
|
|
88
|
+
const testGenToken = (0, scenarios_1.buildTokenFromOptions)({ name: testName, file: filePath }, { useComputerUseAgent: true });
|
|
87
89
|
console.log("[generateTestWithBrowserAgent] Validations passed, starting agent");
|
|
88
90
|
const agentResult = await (0, run_1.runBrowsingAgent)({
|
|
89
91
|
testCaseName: testName,
|
|
@@ -100,10 +102,7 @@ exports.generateTestWithBrowserAgent = {
|
|
|
100
102
|
// Cleanup: Undo the TODO -> createTest changes
|
|
101
103
|
await (0, pw_pause_1.revertToOriginalPwCode)(repoPath);
|
|
102
104
|
fs_1.default.writeFileSync(absoluteFilePath, fileBackup, "utf-8");
|
|
103
|
-
const { isError, error, result: toolResult,
|
|
104
|
-
if (artifacts) {
|
|
105
|
-
void collectArtifacts?.(artifacts);
|
|
106
|
-
}
|
|
105
|
+
const { isError, error, result: toolResult, usage } = agentResult;
|
|
107
106
|
if (isError || !toolResult) {
|
|
108
107
|
return {
|
|
109
108
|
isError,
|
|
@@ -112,53 +111,58 @@ ${error}
|
|
|
112
111
|
`,
|
|
113
112
|
};
|
|
114
113
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
const screenshotArtifacts = toolResult
|
|
115
|
+
.filter((item) => item.type === "screenshot")
|
|
116
|
+
.map((item) => item.screenshot)
|
|
117
|
+
.map((artifact) => ({
|
|
118
|
+
...artifact,
|
|
119
|
+
data: Buffer.isBuffer(artifact.data)
|
|
120
|
+
? artifact.data
|
|
121
|
+
: Buffer.from(artifact.data),
|
|
122
|
+
}));
|
|
123
|
+
const artifactsInput = [
|
|
124
|
+
...((0, utils_2.findPlaywrightArtifacts)(repoPath) || []),
|
|
125
|
+
...screenshotArtifacts,
|
|
126
|
+
];
|
|
127
|
+
const summaryResult = `Browser agent has finished running.
|
|
128
|
+
TODO comment which it worked on: ${todoContent}
|
|
129
|
+
Summary of actions it took, and the generated Playwright code:`;
|
|
130
|
+
if (!collectArtifacts || artifactsInput.length === 0) {
|
|
131
|
+
const result = [
|
|
132
|
+
{ type: "text", text: summaryResult },
|
|
133
|
+
...toolResult.map((item) => ({
|
|
134
|
+
type: "text",
|
|
135
|
+
text: item.type === "text" ? item.text : "[Screenshot]",
|
|
136
|
+
})),
|
|
137
|
+
];
|
|
138
|
+
return { isError, result, usage };
|
|
139
|
+
}
|
|
140
|
+
const uploadedArtifacts = await collectArtifacts(artifactsInput);
|
|
141
|
+
const artifactUrlMap = new Map(uploadedArtifacts.map((a) => [a.name, a.url]));
|
|
142
|
+
let screenshotIndex = 0;
|
|
143
|
+
const result = [
|
|
144
|
+
{ type: "text", text: summaryResult },
|
|
120
145
|
...toolResult.map((item) => {
|
|
121
146
|
if (item.type === "text") {
|
|
122
|
-
return {
|
|
123
|
-
type: "text",
|
|
124
|
-
text: item.text,
|
|
125
|
-
};
|
|
147
|
+
return { type: "text", text: item.text };
|
|
126
148
|
}
|
|
127
149
|
else if (item.type === "screenshot") {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
else {
|
|
137
|
-
return {
|
|
138
|
-
type: "text",
|
|
139
|
-
text: `Unknown item type: ${item}`,
|
|
140
|
-
};
|
|
150
|
+
const screenshotName = screenshotArtifacts[screenshotIndex]?.name;
|
|
151
|
+
const url = screenshotName
|
|
152
|
+
? artifactUrlMap.get(screenshotName)
|
|
153
|
+
: undefined;
|
|
154
|
+
screenshotIndex++;
|
|
155
|
+
return url
|
|
156
|
+
? { type: "image/png", url }
|
|
157
|
+
: { type: "text", text: "[Screenshot upload failed]" };
|
|
141
158
|
}
|
|
159
|
+
return { type: "text", text: "Unknown item type" };
|
|
142
160
|
}),
|
|
143
161
|
];
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
usage,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
const textOnlyResult = result
|
|
154
|
-
.filter((item) => item.type === "text")
|
|
155
|
-
.map((item) => item.text)
|
|
156
|
-
.join("\n");
|
|
157
|
-
return {
|
|
158
|
-
isError,
|
|
159
|
-
result: textOnlyResult,
|
|
160
|
-
usage,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
162
|
+
return {
|
|
163
|
+
isError,
|
|
164
|
+
result,
|
|
165
|
+
usage,
|
|
166
|
+
};
|
|
163
167
|
},
|
|
164
168
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAcvD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,eAAO,MAAM,sBAAsB,EAAE,IAkHpC,CAAC"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.fetchTestRunReportTool = void 0;
|
|
4
4
|
exports.extractPathAfterSourceRepo = extractPathAfterSourceRepo;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
const urls_1 = require("../utils/urls");
|
|
6
7
|
const TestRunSchema = zod_1.z.object({
|
|
7
8
|
testRunUrl: zod_1.z
|
|
8
9
|
.string()
|
|
@@ -26,23 +27,12 @@ exports.fetchTestRunReportTool = {
|
|
|
26
27
|
needsBrowser: false,
|
|
27
28
|
isInlineTool: true,
|
|
28
29
|
execute: async ({ input, apiClient }) => {
|
|
29
|
-
const { testRunUrl } = input;
|
|
30
|
-
// Remove query parameters if they exist
|
|
31
|
-
const urlWithoutParams = testRunUrl.split("?")[0] || testRunUrl;
|
|
32
|
-
// Extract the run ID and repo name from the URL
|
|
33
|
-
const urlParts = urlWithoutParams.split("/");
|
|
34
|
-
const runId = urlParts.pop(); // Last part is the run ID
|
|
35
|
-
const repoName = urlParts[urlParts.length - 2]; // Second to last part is the repo name
|
|
36
|
-
if (!runId || !repoName) {
|
|
37
|
-
return {
|
|
38
|
-
isError: true,
|
|
39
|
-
result: "Invalid test run URL - could not extract run ID or repo name",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
let data = null;
|
|
43
30
|
if (!apiClient) {
|
|
44
31
|
throw new Error("Dashboard API client is not available.");
|
|
45
32
|
}
|
|
33
|
+
const { testRunUrl } = input;
|
|
34
|
+
let data = null;
|
|
35
|
+
const { repoName, runId } = (0, urls_1.extractProjectFromUrl)(testRunUrl);
|
|
46
36
|
try {
|
|
47
37
|
data = await apiClient.request(`/api/test-runs/${runId}?repo_name=${repoName}`, { method: "GET" });
|
|
48
38
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../../src/tools/utils/urls.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM;;;EAiBvD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractProjectFromUrl = extractProjectFromUrl;
|
|
4
|
+
function extractProjectFromUrl(testRunUrl) {
|
|
5
|
+
// Remove query parameters if they exist
|
|
6
|
+
const urlWithoutParams = testRunUrl.split("?")[0] || testRunUrl;
|
|
7
|
+
// Extract the run ID and repo name from the URL
|
|
8
|
+
const urlParts = urlWithoutParams.split("/");
|
|
9
|
+
const runId = urlParts.pop();
|
|
10
|
+
const projectSlug = urlParts[urlParts.length - 2];
|
|
11
|
+
if (!runId || !projectSlug) {
|
|
12
|
+
throw new Error("Invalid test run URL - could not extract run ID or project slug");
|
|
13
|
+
}
|
|
14
|
+
const repoName = `${projectSlug}-tests`;
|
|
15
|
+
return {
|
|
16
|
+
repoName,
|
|
17
|
+
runId,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/view-failed-test-run-report/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/view-failed-test-run-report/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,6BAA6B;;;;;;EAExC,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAChD,OAAO,6BAA6B,CACrC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,IAsKzC,CAAC"}
|
|
@@ -4,6 +4,7 @@ exports.viewFailedTestRunReportTool = exports.ViewFailedTestRunReportSchema = vo
|
|
|
4
4
|
// import fs from "fs";
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const playwright_report_parser_1 = require("../../utils/playwright-report-parser");
|
|
7
|
+
const urls_1 = require("../utils/urls");
|
|
7
8
|
exports.ViewFailedTestRunReportSchema = zod_1.z.object({
|
|
8
9
|
testRunUrl: zod_1.z.string().describe("The URL of the test run to process."),
|
|
9
10
|
});
|
|
@@ -17,18 +18,7 @@ exports.viewFailedTestRunReportTool = {
|
|
|
17
18
|
isInlineTool: true,
|
|
18
19
|
execute: async ({ input, apiClient }) => {
|
|
19
20
|
const { testRunUrl } = input;
|
|
20
|
-
|
|
21
|
-
const urlWithoutParams = testRunUrl.split("?")[0] || testRunUrl;
|
|
22
|
-
// Extract the run ID and repo name from the URL
|
|
23
|
-
const urlParts = urlWithoutParams.split("/");
|
|
24
|
-
const runId = urlParts.pop(); // Last part is the run ID
|
|
25
|
-
const repoName = urlParts[urlParts.length - 2]; // Second to last part is the repo name
|
|
26
|
-
if (!runId || !repoName) {
|
|
27
|
-
return {
|
|
28
|
-
isError: true,
|
|
29
|
-
result: "Invalid test run URL - could not extract run ID or repo name",
|
|
30
|
-
};
|
|
31
|
-
}
|
|
21
|
+
const { repoName, runId } = (0, urls_1.extractProjectFromUrl)(testRunUrl);
|
|
32
22
|
let result = {
|
|
33
23
|
testRun: null,
|
|
34
24
|
summary: null,
|
|
@@ -80,9 +70,7 @@ exports.viewFailedTestRunReportTool = {
|
|
|
80
70
|
// );
|
|
81
71
|
const htmlDetailed = await apiClient.request(`/api/reports/html-detailed`, {
|
|
82
72
|
method: "GET",
|
|
83
|
-
params: {
|
|
84
|
-
url: indexHtmlUrl,
|
|
85
|
-
},
|
|
73
|
+
params: { url: indexHtmlUrl },
|
|
86
74
|
});
|
|
87
75
|
const parsedReport = (0, playwright_report_parser_1.parsePlaywrightTestReport)(summaryData);
|
|
88
76
|
// fs.writeFileSync(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* root/ (= baseArtifactDir)
|
|
3
|
+
* - video_<videoUrlHash>.webm (= videoFile)
|
|
4
|
+
* - chunk_1.mp4
|
|
5
|
+
* - consolidated_frames/ (= consolidatedFramesDir)
|
|
6
|
+
* - frame_0001.png
|
|
7
|
+
* - frame_0002.png
|
|
8
|
+
* - ...
|
|
9
|
+
* - unique_frames/ (= uniqueFramesDir)
|
|
10
|
+
* - frame_0002.png
|
|
11
|
+
* - ...
|
|
12
|
+
*/
|
|
13
|
+
export interface VideoArtifactPaths {
|
|
14
|
+
baseArtifactDir: string;
|
|
15
|
+
videoFile: string;
|
|
16
|
+
consolidatedFramesDir: string;
|
|
17
|
+
uniqueFramesDir: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function resolveVideoArtifactPaths(artifactsPath: string, videoUrlHash: string): VideoArtifactPaths;
|
|
20
|
+
//# sourceMappingURL=artifact-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-paths.d.ts","sourceRoot":"","sources":["../../src/utils/artifact-paths.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,kBAAkB;IAEjC,eAAe,EAAE,MAAM,CAAC;IAExB,SAAS,EAAE,MAAM,CAAC;IAElB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACnB,kBAAkB,CAQpB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
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.resolveVideoArtifactPaths = resolveVideoArtifactPaths;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
function resolveVideoArtifactPaths(artifactsPath, videoUrlHash) {
|
|
9
|
+
const baseArtifactDir = artifactsPath;
|
|
10
|
+
return {
|
|
11
|
+
baseArtifactDir,
|
|
12
|
+
videoFile: node_path_1.default.join(baseArtifactDir, `video_${videoUrlHash}.webm`),
|
|
13
|
+
consolidatedFramesDir: node_path_1.default.join(baseArtifactDir, "consolidated_frames"),
|
|
14
|
+
uniqueFramesDir: node_path_1.default.join(baseArtifactDir, "unique_frames"),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Processes an array of image file paths and returns only unique images as base64 strings.
|
|
3
|
-
* This is a file system wrapper around the deduplicateImages function that processes
|
|
4
|
-
* images in batches to avoid memory overflow.
|
|
5
|
-
*
|
|
6
|
-
* @param options - Configuration options
|
|
7
|
-
* @param options.imagePaths - An array of file paths to image files.
|
|
8
|
-
* @param options.batchSize - Number of images to process at a time (default: 50)
|
|
9
|
-
* @param options.threshold - The maximum fraction of pixels allowed to differ to consider two images similar.
|
|
10
|
-
* For example, 0.01 means that if less than 1% of the pixels differ, the images are considered duplicates.
|
|
11
|
-
* Default is 0.001 (0.1%).
|
|
12
|
-
* @param options.logPrefix - The ID of the test run, used for logging purposes.
|
|
13
|
-
* @returns A promise that resolves to an array of unique image objects with base64 data.
|
|
14
|
-
*/
|
|
15
1
|
export declare function deduplicateImageFiles({ imagePaths, batchSize, threshold, logPrefix, }: {
|
|
16
2
|
imagePaths: string[];
|
|
17
|
-
batchSize
|
|
18
|
-
threshold
|
|
3
|
+
batchSize: number;
|
|
4
|
+
threshold: number;
|
|
19
5
|
logPrefix?: string;
|
|
20
6
|
}): Promise<{
|
|
21
7
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedup-image-fs.d.ts","sourceRoot":"","sources":["../../src/utils/dedup-image-fs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dedup-image-fs.d.ts","sourceRoot":"","sources":["../../src/utils/dedup-image-fs.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB,CAAC,EAC1C,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAA4B,GAC7B,EAAE;IACD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CA2G1E"}
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.deduplicateImageFiles = deduplicateImageFiles;
|
|
4
7
|
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
5
9
|
const dedup_image_1 = require("./dedup-image");
|
|
6
|
-
|
|
7
|
-
* Processes an array of image file paths and returns only unique images as base64 strings.
|
|
8
|
-
* This is a file system wrapper around the deduplicateImages function that processes
|
|
9
|
-
* images in batches to avoid memory overflow.
|
|
10
|
-
*
|
|
11
|
-
* @param options - Configuration options
|
|
12
|
-
* @param options.imagePaths - An array of file paths to image files.
|
|
13
|
-
* @param options.batchSize - Number of images to process at a time (default: 50)
|
|
14
|
-
* @param options.threshold - The maximum fraction of pixels allowed to differ to consider two images similar.
|
|
15
|
-
* For example, 0.01 means that if less than 1% of the pixels differ, the images are considered duplicates.
|
|
16
|
-
* Default is 0.001 (0.1%).
|
|
17
|
-
* @param options.logPrefix - The ID of the test run, used for logging purposes.
|
|
18
|
-
* @returns A promise that resolves to an array of unique image objects with base64 data.
|
|
19
|
-
*/
|
|
20
|
-
async function deduplicateImageFiles({ imagePaths, batchSize = 50, threshold = 0.001, logPrefix = "dedup-image-fs", }) {
|
|
10
|
+
async function deduplicateImageFiles({ imagePaths, batchSize, threshold, logPrefix = "dedup-image-fs", }) {
|
|
21
11
|
const uniqueImages = [];
|
|
22
12
|
console.log(`[${logPrefix}] Processing ${imagePaths.length} images in batches of ${batchSize}`);
|
|
23
13
|
for (let i = 0; i < imagePaths.length; i += batchSize) {
|
|
@@ -33,9 +23,15 @@ async function deduplicateImageFiles({ imagePaths, batchSize = 50, threshold = 0
|
|
|
33
23
|
try {
|
|
34
24
|
const buffer = await fs_1.promises.readFile(imagePath);
|
|
35
25
|
const base64 = buffer.toString("base64");
|
|
26
|
+
// Extract actual frame number from filename instead of using serial index
|
|
27
|
+
const filename = path_1.default.basename(imagePath);
|
|
28
|
+
const frameNumberMatch = filename.match(/frame_(\d+)\.png$/);
|
|
29
|
+
const frameIndex = frameNumberMatch
|
|
30
|
+
? parseInt(frameNumberMatch[1], 10)
|
|
31
|
+
: i + j; // Fallback to serial index if no match
|
|
36
32
|
batchBase64Images.push({
|
|
37
33
|
metadata: {
|
|
38
|
-
index:
|
|
34
|
+
index: frameIndex,
|
|
39
35
|
path: imagePath,
|
|
40
36
|
},
|
|
41
37
|
image: base64,
|
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Processes an array of base64 image objects and returns only unique images.
|
|
3
|
-
* Two images are considered "similar" if the fraction of differing pixels (when resized)
|
|
4
|
-
* is below the provided threshold.
|
|
5
|
-
*
|
|
6
|
-
* @param options - Configuration options
|
|
7
|
-
* @param options.base64Images - An array of objects, each with a metadata field and a base64-encoded image string.
|
|
8
|
-
* @param options.threshold - The maximum fraction of pixels allowed to differ to consider two images similar.
|
|
9
|
-
* For example, 0.01 means that if less than 1% of the pixels differ, the images are considered duplicates.
|
|
10
|
-
* Default is 0.001 (0.1%).
|
|
11
|
-
* @param options.logPrefix - The ID of the test run, used for logging purposes.
|
|
12
|
-
* @returns A promise that resolves to an array of unique image objects.
|
|
13
|
-
*/
|
|
14
1
|
export declare function deduplicateImages({ base64Images, threshold, logPrefix, }: {
|
|
15
2
|
base64Images: {
|
|
16
3
|
metadata: any;
|
|
17
4
|
image: string;
|
|
18
5
|
}[];
|
|
19
|
-
threshold
|
|
6
|
+
threshold: number;
|
|
20
7
|
logPrefix?: string;
|
|
21
8
|
}): Promise<{
|
|
22
9
|
metadata: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedup-image.d.ts","sourceRoot":"","sources":["../../src/utils/dedup-image.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dedup-image.d.ts","sourceRoot":"","sources":["../../src/utils/dedup-image.ts"],"names":[],"mappings":"AAEA,wBAAsB,iBAAiB,CAAC,EACtC,YAAY,EACZ,SAAS,EACT,SAAyB,GAC1B,EAAE;IACD,YAAY,EAAE;QAAE,QAAQ,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CA0B9C"}
|