@empiricalrun/test-gen 0.80.1 → 0.80.3
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 +14 -0
- package/dist/agent/chat/exports.d.ts +1 -1
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +3 -4
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +10 -4
- package/dist/agent/chat/prompt/skills.d.ts +3 -0
- package/dist/agent/chat/prompt/skills.d.ts.map +1 -0
- package/dist/agent/chat/prompt/skills.js +36 -0
- package/dist/agent/triage/index.d.ts.map +1 -1
- package/dist/agent/triage/index.js +2 -1
- package/dist/file-info/adapters/github/reader.d.ts +1 -9
- package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
- package/dist/file-info/adapters/github/reader.js +8 -130
- package/dist/file-info/index.d.ts +0 -1
- package/dist/file-info/index.d.ts.map +1 -1
- package/dist/file-info/index.js +1 -3
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +2 -0
- package/dist/tools/api-client/index.d.ts.map +1 -1
- package/dist/tools/api-client/index.js +88 -0
- package/dist/tools/index.d.ts +1 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -23
- package/dist/tools/safe-bash/index.d.ts.map +1 -1
- package/dist/tools/safe-bash/index.js +52 -2
- package/dist/tools/slack-message/index.d.ts.map +1 -1
- package/dist/tools/slack-message/index.js +13 -0
- package/dist/tools/test-run-fetcher/types.d.ts +0 -36
- package/dist/tools/test-run-fetcher/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/file-info/adapters/github/index.d.ts +0 -12
- package/dist/file-info/adapters/github/index.d.ts.map +0 -1
- package/dist/file-info/adapters/github/index.js +0 -29
- package/dist/tools/utils/queue.d.ts +0 -5
- package/dist/tools/utils/queue.d.ts.map +0 -1
- package/dist/tools/utils/queue.js +0 -41
- package/dist/utils/SQSClient.d.ts +0 -14
- package/dist/utils/SQSClient.d.ts.map +0 -1
- package/dist/utils/SQSClient.js +0 -116
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @empiricalrun/test-gen
|
|
2
2
|
|
|
3
|
+
## 0.80.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [12b14e5]
|
|
8
|
+
- @empiricalrun/dashboard-client@0.3.0
|
|
9
|
+
|
|
10
|
+
## 0.80.2
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [2d6f146]
|
|
15
|
+
- @empiricalrun/dashboard-client@0.2.1
|
|
16
|
+
|
|
3
17
|
## 0.80.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { IChatModel } from "@empiricalrun/llm/chat";
|
|
2
2
|
export { createChatModel } from "@empiricalrun/llm/chat";
|
|
3
3
|
export { SUPPORTED_CHAT_MODELS } from "@empiricalrun/llm/chat/constants";
|
|
4
|
-
export { getFileInfoFromGitHub
|
|
4
|
+
export { getFileInfoFromGitHub } from "../../file-info/adapters/github/reader";
|
|
5
5
|
export type { AgentParams, OnToolCallCallback } from "../base";
|
|
6
6
|
export { BaseAgent } from "../base";
|
|
7
7
|
export type { CodeReviewResultV0, CodeReviewResultV1, CodeReviewResultV2, CodeReviewVersionedResult, } from "../code-review";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/exports.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/exports.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAE/E,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractAttachments = exports.LATEST_CHAT_STATE_VERSION = exports.fetchToolCallFromId = exports.ChatAgent = exports.TriageAgent = exports.FastTriageAgent = exports.CodeReviewAgent = exports.BaseAgent = exports.
|
|
3
|
+
exports.extractAttachments = exports.LATEST_CHAT_STATE_VERSION = exports.fetchToolCallFromId = exports.ChatAgent = exports.TriageAgent = exports.FastTriageAgent = exports.CodeReviewAgent = exports.BaseAgent = exports.getFileInfoFromGitHub = exports.SUPPORTED_CHAT_MODELS = exports.createChatModel = void 0;
|
|
4
4
|
var chat_1 = require("@empiricalrun/llm/chat");
|
|
5
5
|
Object.defineProperty(exports, "createChatModel", { enumerable: true, get: function () { return chat_1.createChatModel; } });
|
|
6
6
|
var constants_1 = require("@empiricalrun/llm/chat/constants");
|
|
7
7
|
Object.defineProperty(exports, "SUPPORTED_CHAT_MODELS", { enumerable: true, get: function () { return constants_1.SUPPORTED_CHAT_MODELS; } });
|
|
8
|
-
var
|
|
9
|
-
Object.defineProperty(exports, "getFileInfoFromGitHub", { enumerable: true, get: function () { return
|
|
10
|
-
Object.defineProperty(exports, "viewFileUsingGitHub", { enumerable: true, get: function () { return github_1.viewFileUsingGitHub; } });
|
|
8
|
+
var reader_1 = require("../../file-info/adapters/github/reader");
|
|
9
|
+
Object.defineProperty(exports, "getFileInfoFromGitHub", { enumerable: true, get: function () { return reader_1.getFileInfoFromGitHub; } });
|
|
11
10
|
var base_1 = require("../base");
|
|
12
11
|
Object.defineProperty(exports, "BaseAgent", { enumerable: true, get: function () { return base_1.BaseAgent; } });
|
|
13
12
|
var code_review_1 = require("../code-review");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAsBpE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAOpC,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,QAAQ,IAAI,WAAW;IA8B3B,iBAAiB,CACrB,eAAe,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC;CA0GnB"}
|
package/dist/agent/chat/index.js
CHANGED
|
@@ -7,31 +7,35 @@ const analyse_video_1 = require("../../tools/definitions/analyse-video");
|
|
|
7
7
|
const grep_1 = require("../../tools/definitions/grep");
|
|
8
8
|
const list_tests_and_projects_1 = require("../../tools/definitions/list-tests-and-projects");
|
|
9
9
|
const run_test_1 = require("../../tools/definitions/run-test");
|
|
10
|
+
const test_gen_browser_1 = require("../../tools/definitions/test-gen-browser");
|
|
10
11
|
const diagnosis_fetcher_1 = require("../../tools/diagnosis-fetcher");
|
|
11
12
|
const fetch_file_1 = require("../../tools/fetch-file");
|
|
12
13
|
const slack_message_1 = require("../../tools/slack-message");
|
|
13
14
|
const base_1 = require("../base");
|
|
14
15
|
const pw_utils_docs_1 = require("./prompt/pw-utils-docs");
|
|
15
16
|
const repo_1 = require("./prompt/repo");
|
|
17
|
+
const skills_1 = require("./prompt/skills");
|
|
16
18
|
const test_case_def_1 = require("./prompt/test-case-def");
|
|
17
19
|
const trace_utils_docs_1 = require("./prompt/trace-utils-docs");
|
|
18
20
|
class ChatAgent extends base_1.BaseAgent {
|
|
19
21
|
getTools() {
|
|
20
22
|
const hasSlackTool = this.featureFlags.includes("has_slack_tool");
|
|
23
|
+
const hasSkills = this.featureFlags.includes("useSkills");
|
|
24
|
+
const hasAnalyseVideoTool = this.featureFlags.includes("has_analyse_video_tool");
|
|
21
25
|
const custom = [
|
|
22
|
-
analyse_video_1.analyseVideo,
|
|
26
|
+
...(hasAnalyseVideoTool ? [analyse_video_1.analyseVideo] : []),
|
|
23
27
|
run_test_1.runTestTool,
|
|
24
28
|
grep_1.grepTool,
|
|
25
|
-
api_client_1.apiClientTool,
|
|
26
29
|
...(hasSlackTool ? [slack_message_1.slackMessageTool] : []),
|
|
27
30
|
fetch_file_1.fetchFileTool,
|
|
28
31
|
list_tests_and_projects_1.listProjectsTool,
|
|
29
32
|
list_tests_and_projects_1.listTestsForProjectTool,
|
|
30
|
-
...tools_1.testGenerationTools,
|
|
31
33
|
diagnosis_fetcher_1.fetchDiagnosisReportTool,
|
|
32
34
|
...(0, tools_1.textEditorToolsForModel)(this.selectedModel),
|
|
33
35
|
tools_1.safeBashTool,
|
|
34
36
|
...(!(0, tools_1.hasBuiltInWebFetch)(this.selectedModel) ? [tools_1.scrapeHtmlTool] : []),
|
|
37
|
+
...tools_1.testGenerationToolsWithoutBrowserAgent,
|
|
38
|
+
...(!hasSkills ? [api_client_1.apiClientTool, test_gen_browser_1.generateTestWithBrowserAgent] : []),
|
|
35
39
|
];
|
|
36
40
|
return {
|
|
37
41
|
custom,
|
|
@@ -44,6 +48,8 @@ class ChatAgent extends base_1.BaseAgent {
|
|
|
44
48
|
async buildSystemPrompt(repoInfoBuilder) {
|
|
45
49
|
const repoInfo = await repoInfoBuilder();
|
|
46
50
|
const repoContext = await (0, repo_1.getRepoContextPrompt)(repoInfo);
|
|
51
|
+
const hasSkills = this.featureFlags.includes("useSkills");
|
|
52
|
+
const skillsInToolsPrompt = hasSkills ? skills_1.skillsToolsPrompt : "";
|
|
47
53
|
const preamble = `
|
|
48
54
|
You are a helpful assistant that can answer questions and help with tasks related to writing and maintaining Playwright tests.
|
|
49
55
|
|
|
@@ -69,7 +75,7 @@ fixed with modifications to the test code, and it is your job to do that.
|
|
|
69
75
|
|
|
70
76
|
You are given a set of tools (= functions) to help you fulfill the user's request. Read their descriptions
|
|
71
77
|
to understand what each tool does. You are HIGHLY encouraged to use tools and generate a high quality output.
|
|
72
|
-
|
|
78
|
+
${skillsInToolsPrompt}
|
|
73
79
|
For example,
|
|
74
80
|
|
|
75
81
|
1. If you are adding or modifying a test, run the test to ensure it works well.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const skillsToolsPrompt: string;
|
|
2
|
+
export declare const skillsProactivenessPrompt = "\nIf your listed tools don't seem sufficient for a task, load a relevant skill file using the bash tool to learn how to accomplish the task with your existing tools.\n";
|
|
3
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../../src/agent/chat/prompt/skills.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,iBAAiB,QAO7B,CAAC;AAEF,eAAO,MAAM,yBAAyB,4KAErC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.skillsProactivenessPrompt = exports.skillsToolsPrompt = void 0;
|
|
4
|
+
const availableSkills = [
|
|
5
|
+
{
|
|
6
|
+
name: "empirical-api",
|
|
7
|
+
description: "Interact with the Empirical dashboard via API. Load this skill whenever you need to access dashboard data such as test runs, resources, or any project-level information.",
|
|
8
|
+
location: "/opt/skills/empirical-api/SKILL.md",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
name: "playwright-cli",
|
|
12
|
+
description: "Interact with browsers via playwright-cli for test generation, debugging, and exploration. Use when asked to generate, modify, or fix Playwright tests, explore a website or debug test failures.",
|
|
13
|
+
location: "/opt/skills/playwright-cli/SKILL.md",
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
const skillToXml = (s) => {
|
|
17
|
+
return `<skill>
|
|
18
|
+
<name>${s.name}</name>
|
|
19
|
+
<description>${s.description}</description>
|
|
20
|
+
<location>${s.location}</location>
|
|
21
|
+
</skill>`;
|
|
22
|
+
};
|
|
23
|
+
const skillCatalogXml = `<available_skills>
|
|
24
|
+
${availableSkills.map(skillToXml).join("\n")}
|
|
25
|
+
</available_skills>`;
|
|
26
|
+
exports.skillsToolsPrompt = `
|
|
27
|
+
You have access to **skill files** — documentation that teaches you how to accomplish tasks using your existing safeBash tool.
|
|
28
|
+
Skills are NOT callable functions. To use a skill, read its file with bash, then follow the instructions inside.
|
|
29
|
+
|
|
30
|
+
${skillCatalogXml}
|
|
31
|
+
|
|
32
|
+
To use a skill: run \`cat <location>\` using the bash tool, then follow the instructions in the output.
|
|
33
|
+
`;
|
|
34
|
+
exports.skillsProactivenessPrompt = `
|
|
35
|
+
If your listed tools don't seem sufficient for a task, load a relevant skill file using the bash tool to learn how to accomplish the task with your existing tools.
|
|
36
|
+
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/triage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAepE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,qBAAa,WAAW,CAAC,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC9C,SAAS,CAAC,QAAQ,IAAI,WAAW;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/triage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAepE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIpC,qBAAa,WAAW,CAAC,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC9C,SAAS,CAAC,QAAQ,IAAI,WAAW;cA6BjB,iBAAiB,CAC/B,eAAe,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC;CAgEnB"}
|
|
@@ -19,6 +19,7 @@ const repo_1 = require("../chat/prompt/repo");
|
|
|
19
19
|
const test_case_def_1 = require("../chat/prompt/test-case-def");
|
|
20
20
|
class TriageAgent extends base_1.BaseAgent {
|
|
21
21
|
getTools() {
|
|
22
|
+
const hasAnalyseVideoTool = this.featureFlags.includes("has_analyse_video_tool");
|
|
22
23
|
const tools = [
|
|
23
24
|
// Tools to understand test run (open report)
|
|
24
25
|
diagnosis_fetcher_1.fetchDiagnosisReportTool,
|
|
@@ -26,7 +27,7 @@ class TriageAgent extends base_1.BaseAgent {
|
|
|
26
27
|
list_environments_1.listEnvironmentsTool,
|
|
27
28
|
// Tools to analyse report artifacts
|
|
28
29
|
fetch_file_1.fetchFileTool,
|
|
29
|
-
analyse_video_1.analyseVideo,
|
|
30
|
+
...(hasAnalyseVideoTool ? [analyse_video_1.analyseVideo] : []),
|
|
30
31
|
trace_dot_zip_1.traceDotZip,
|
|
31
32
|
// Tools to get test case context from the repo
|
|
32
33
|
grep_1.grepTool,
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { IDashboardAPIClient } from "@empiricalrun/shared-types/api/base";
|
|
2
|
-
import { FileInfo
|
|
3
|
-
export declare class GitHubFileReader {
|
|
4
|
-
private repoName;
|
|
5
|
-
private apiClient;
|
|
6
|
-
constructor(repoName: string, apiClient: IDashboardAPIClient);
|
|
7
|
-
resolveBranchName(branchName: string | undefined, baseBranch: string): Promise<string>;
|
|
8
|
-
readFile(filePath: string, branchName: string, baseBranch: string): Promise<FileReadResult | null>;
|
|
9
|
-
private readDirectory;
|
|
10
|
-
}
|
|
2
|
+
import { FileInfo } from "@empiricalrun/shared-types/test-gen";
|
|
11
3
|
export declare function getFileInfoFromGitHub(repoName: string, apiClient: IDashboardAPIClient, branchName: string, baseBranchName: string): Promise<FileInfo>;
|
|
12
4
|
//# sourceMappingURL=reader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAqF/D,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC,CAyFnB"}
|
|
@@ -3,134 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.GitHubFileReader = void 0;
|
|
7
6
|
exports.getFileInfoFromGitHub = getFileInfoFromGitHub;
|
|
8
7
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function
|
|
10
|
-
const base = path_1.default.basename(filename);
|
|
11
|
-
return base.startsWith(".") && base !== "." && base !== "..";
|
|
12
|
-
}
|
|
13
|
-
function isDirectory(filename) {
|
|
14
|
-
const hasFileExtension = path_1.default.extname(filename) !== "";
|
|
15
|
-
return !isDotfile(filename) && !hasFileExtension;
|
|
16
|
-
}
|
|
17
|
-
class GitHubFileReader {
|
|
18
|
-
repoName;
|
|
19
|
-
apiClient;
|
|
20
|
-
constructor(repoName, apiClient) {
|
|
21
|
-
this.repoName = repoName;
|
|
22
|
-
this.apiClient = apiClient;
|
|
23
|
-
}
|
|
24
|
-
async resolveBranchName(branchName, baseBranch) {
|
|
25
|
-
if (!branchName || branchName === baseBranch) {
|
|
26
|
-
return baseBranch;
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
await this.apiClient.callGitHubProxy({
|
|
30
|
-
method: "GET",
|
|
31
|
-
url: `/repos/empirical-run/${this.repoName}/branches/${branchName}`,
|
|
32
|
-
});
|
|
33
|
-
console.log(`[GitHubFileReader] Branch ${branchName} exists`);
|
|
34
|
-
return branchName;
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
console.log(`[GitHubFileReader] Branch ${branchName} not found, falling back to ${baseBranch}`);
|
|
38
|
-
return baseBranch;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async readFile(filePath, branchName, baseBranch) {
|
|
42
|
-
const resolvedBranch = await this.resolveBranchName(branchName, baseBranch);
|
|
43
|
-
if (isDirectory(filePath)) {
|
|
44
|
-
console.log(`[GitHubFileReader] Reading as directory: ${filePath}`);
|
|
45
|
-
return this.readDirectory(filePath, resolvedBranch);
|
|
46
|
-
}
|
|
47
|
-
// For dotfiles without extensions (e.g. .empiricalrun, .github), we can't
|
|
48
|
-
// tell if they're files or directories by name alone. Try directory first
|
|
49
|
-
// since that API is faster and won't hang for misclassified paths.
|
|
50
|
-
if (isDotfile(filePath) && !path_1.default.extname(filePath)) {
|
|
51
|
-
console.log(`[GitHubFileReader] Dotfile without extension, trying directory first: ${filePath}`);
|
|
52
|
-
const dirResult = await this.readDirectory(filePath, resolvedBranch);
|
|
53
|
-
if (dirResult) {
|
|
54
|
-
return dirResult;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
console.log(`[GitHubFileReader] Reading as file: ${filePath}, resolved branch: ${resolvedBranch}`);
|
|
59
|
-
const params = {
|
|
60
|
-
repo: this.repoName,
|
|
61
|
-
path: filePath,
|
|
62
|
-
ref: resolvedBranch,
|
|
63
|
-
};
|
|
64
|
-
const response = await this.apiClient.request(`/api/github/files`, {
|
|
65
|
-
method: "GET",
|
|
66
|
-
params,
|
|
67
|
-
});
|
|
68
|
-
if (response.data?.fileContents.available) {
|
|
69
|
-
return {
|
|
70
|
-
content: response.data.fileContents.content,
|
|
71
|
-
isDirectory: false,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
console.log(`[GitHubFileReader] File not available: ${filePath}`);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
console.log(`[GitHubFileReader] Error reading file ${filePath}:`, error);
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async readDirectory(filePath, resolvedBranch) {
|
|
83
|
-
try {
|
|
84
|
-
console.log(`[GitHubFileReader] Reading directory: ${filePath}, resolved branch: ${resolvedBranch}`);
|
|
85
|
-
const params = {
|
|
86
|
-
repo: this.repoName,
|
|
87
|
-
path: filePath || ".", // Handle empty path
|
|
88
|
-
ref: resolvedBranch,
|
|
89
|
-
};
|
|
90
|
-
const treeResponse = await this.apiClient.request(`/api/github/tree`, {
|
|
91
|
-
method: "GET",
|
|
92
|
-
params,
|
|
93
|
-
});
|
|
94
|
-
if (treeResponse.data?.tree) {
|
|
95
|
-
const targetPath = filePath === "." || filePath === "" ? "" : filePath;
|
|
96
|
-
const files = treeResponse.data.tree.tree
|
|
97
|
-
.map((item) => item.path)
|
|
98
|
-
.filter((itemPath) => {
|
|
99
|
-
if (!itemPath)
|
|
100
|
-
return false;
|
|
101
|
-
// Check if item is a direct child of the target directory
|
|
102
|
-
const itemDir = path_1.default.dirname(itemPath);
|
|
103
|
-
// Normalize "." to "" for root directory comparison
|
|
104
|
-
const normalizedItemDir = itemDir === "." ? "" : itemDir;
|
|
105
|
-
return normalizedItemDir === targetPath;
|
|
106
|
-
})
|
|
107
|
-
.map((itemPath) => path_1.default.basename(itemPath))
|
|
108
|
-
.sort()
|
|
109
|
-
.join("\n");
|
|
110
|
-
if (files.length === 0) {
|
|
111
|
-
// No files means directory is invalid
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
return { content: files, isDirectory: true };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
console.log(`[GitHubFileReader] Error reading directory ${filePath}:`, error);
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
exports.GitHubFileReader = GitHubFileReader;
|
|
126
|
-
async function getFileContent(repoName, path, apiClient, branchName) {
|
|
8
|
+
async function getFileContent(repoName, path, apiClient, branchName, baseBranch) {
|
|
127
9
|
const params = {
|
|
128
10
|
repo: repoName,
|
|
129
11
|
path: path,
|
|
12
|
+
ref: branchName,
|
|
13
|
+
baseBranch,
|
|
130
14
|
};
|
|
131
|
-
if (branchName) {
|
|
132
|
-
params.ref = branchName;
|
|
133
|
-
}
|
|
134
15
|
const response = await apiClient.request(`/api/github/files`, {
|
|
135
16
|
method: "GET",
|
|
136
17
|
params,
|
|
@@ -140,14 +21,13 @@ async function getFileContent(repoName, path, apiClient, branchName) {
|
|
|
140
21
|
}
|
|
141
22
|
return response.data.fileContents.content;
|
|
142
23
|
}
|
|
143
|
-
async function getContentsForDirectory({ repo, path, }, apiClient, branchName) {
|
|
24
|
+
async function getContentsForDirectory({ repo, path, }, apiClient, branchName, baseBranch) {
|
|
144
25
|
const params = {
|
|
145
26
|
repo: repo,
|
|
146
27
|
path: path,
|
|
28
|
+
ref: branchName,
|
|
29
|
+
baseBranch,
|
|
147
30
|
};
|
|
148
|
-
if (branchName) {
|
|
149
|
-
params.ref = branchName;
|
|
150
|
-
}
|
|
151
31
|
const response = await apiClient.request(`/api/github/tree`, {
|
|
152
32
|
method: "GET",
|
|
153
33
|
params,
|
|
@@ -158,9 +38,7 @@ async function getContentsForDirectory({ repo, path, }, apiClient, branchName) {
|
|
|
158
38
|
return response.data.tree;
|
|
159
39
|
}
|
|
160
40
|
async function getFileInfoFromGitHub(repoName, apiClient, branchName, baseBranchName) {
|
|
161
|
-
const
|
|
162
|
-
const resolvedBranch = await fileReader.resolveBranchName(branchName, baseBranchName);
|
|
163
|
-
const files = await getContentsForDirectory({ repo: repoName, path: "" }, apiClient, resolvedBranch);
|
|
41
|
+
const files = await getContentsForDirectory({ repo: repoName, path: "" }, apiClient, branchName, baseBranchName);
|
|
164
42
|
const root = [];
|
|
165
43
|
const nodeMap = {};
|
|
166
44
|
if (!files) {
|
|
@@ -184,7 +62,7 @@ async function getFileInfoFromGitHub(repoName, apiClient, branchName, baseBranch
|
|
|
184
62
|
type: "file",
|
|
185
63
|
path: currentPath,
|
|
186
64
|
name: fileName,
|
|
187
|
-
getContent: async () => getFileContent(repoName, currentPath, apiClient,
|
|
65
|
+
getContent: async () => getFileContent(repoName, currentPath, apiClient, branchName, baseBranchName),
|
|
188
66
|
}
|
|
189
67
|
: {
|
|
190
68
|
type: "directory",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file-info/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file-info/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC"}
|
package/dist/file-info/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getFileInfoFromFS = exports.FilesystemFileReader = exports.viewFileUsingFileSystem = void 0;
|
|
4
4
|
var file_system_1 = require("./adapters/file-system");
|
|
5
5
|
Object.defineProperty(exports, "viewFileUsingFileSystem", { enumerable: true, get: function () { return file_system_1.viewFileUsingFileSystem; } });
|
|
6
6
|
var reader_1 = require("./adapters/file-system/reader");
|
|
7
7
|
Object.defineProperty(exports, "FilesystemFileReader", { enumerable: true, get: function () { return reader_1.FilesystemFileReader; } });
|
|
8
8
|
Object.defineProperty(exports, "getFileInfoFromFS", { enumerable: true, get: function () { return reader_1.getFileInfoFromFS; } });
|
|
9
|
-
var github_1 = require("./adapters/github");
|
|
10
|
-
Object.defineProperty(exports, "viewFileUsingGitHub", { enumerable: true, get: function () { return github_1.viewFileUsingGitHub; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,KAAK,EACN,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAM3E,MAAM,MAAM,YAAY,GAAG;IACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,UAAU,CAC9B,KAAK,EAAE,cAAc,EACrB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,eAAe,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,EACxB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,KAAK,EACN,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAM3E,MAAM,MAAM,YAAY,GAAG;IACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,UAAU,CAC9B,KAAK,EAAE,cAAc,EACrB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,eAAe,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,EACxB,GAAG,CAAC,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhB"}
|
package/dist/telemetry/index.js
CHANGED
|
@@ -80,6 +80,8 @@ async function trackLLMResponse(opts) {
|
|
|
80
80
|
tokens_output: opts.usage.tokens?.output || 0,
|
|
81
81
|
cost_input: opts.usage.cost?.input || 0,
|
|
82
82
|
cost_output: opts.usage.cost?.output || 0,
|
|
83
|
+
tokens_cache_read: opts.usage.tokens?.cache_read || 0,
|
|
84
|
+
tokens_cache_creation: opts.usage.tokens?.cache_creation || 0,
|
|
83
85
|
// Moving project_repo_name -> repo_name for consistency with other events
|
|
84
86
|
project_repo_name: opts.projectRepoName,
|
|
85
87
|
repo_name: opts.projectRepoName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/api-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uCAAuC,CAAC;AAkBlE,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/api-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uCAAuC,CAAC;AAkBlE,eAAO,MAAM,aAAa,EAAE,IA2I3B,CAAC"}
|
|
@@ -39,6 +39,94 @@ Returns: { data: { test_runs: [...], total, limit, offset } }
|
|
|
39
39
|
\`GET /api/test-runs/:id\`
|
|
40
40
|
|
|
41
41
|
Returns: { data: { test_run: { testRun: { id, state, duration, environment_name, environment_slug, build_url, build_branch, commit, run_started_at, run_ended_at, ... } } } }
|
|
42
|
+
|
|
43
|
+
### List files
|
|
44
|
+
\`GET /api/files\`
|
|
45
|
+
|
|
46
|
+
Returns uploaded project files (docs, videos, etc).
|
|
47
|
+
|
|
48
|
+
Query params:
|
|
49
|
+
- page: Page number (1-indexed, default 1)
|
|
50
|
+
- per_page: Items per page (default 20)
|
|
51
|
+
|
|
52
|
+
Returns: { data: { files: [{ id, name, url, description, mime_type, size_bytes, status, access_level, created_at, ... }] }, pagination: { page, per_page, total, total_pages } }
|
|
53
|
+
For link-type files (e.g. Google Sheets), access_level is "read_write", "read", or "none".
|
|
54
|
+
|
|
55
|
+
### Get a file by ID
|
|
56
|
+
\`GET /api/files/:id\`
|
|
57
|
+
|
|
58
|
+
Returns: { data: { file: { id, name, url, description, mime_type, size_bytes, status, created_at, ... } } }
|
|
59
|
+
|
|
60
|
+
### Create a file
|
|
61
|
+
\`POST /api/files\`
|
|
62
|
+
|
|
63
|
+
Body: { project_id: number, name: string, mime_type?: string, size_bytes?: number, url?: string, description?: string }
|
|
64
|
+
|
|
65
|
+
Returns: { data: { file: { id, name, upload_url, ... } } }
|
|
66
|
+
The upload_url is a presigned URL for uploading the file content via PUT.
|
|
67
|
+
|
|
68
|
+
**Link-type files (e.g. Google Sheets):** Pass \`url\` to create a link file instead of uploading. The file is immediately marked as "uploaded" with no R2 storage needed.
|
|
69
|
+
Example: { "name": "Test Cases Sheet", "url": "https://docs.google.com/spreadsheets/d/abc123/edit", "description": "Main test cases tracking sheet" }
|
|
70
|
+
|
|
71
|
+
### Update a file
|
|
72
|
+
\`PATCH /api/files/:id\`
|
|
73
|
+
|
|
74
|
+
Body: { name?: string, description?: string, status?: "uploaded" }
|
|
75
|
+
After uploading file content, set status to "uploaded" to make it visible.
|
|
76
|
+
|
|
77
|
+
Returns: { data: { file: { ... } } }
|
|
78
|
+
|
|
79
|
+
### Delete a file
|
|
80
|
+
\`DELETE /api/files/:id\`
|
|
81
|
+
|
|
82
|
+
Returns: { data: { result: { success: true } } }
|
|
83
|
+
|
|
84
|
+
### Google Sheets proxy
|
|
85
|
+
\`POST /api/gsheet/proxy\`
|
|
86
|
+
|
|
87
|
+
Read, write, or append to a Google Sheet via the dashboard's service account.
|
|
88
|
+
|
|
89
|
+
Body:
|
|
90
|
+
- action: "read" | "write" | "append"
|
|
91
|
+
- spreadsheet_id: The spreadsheet ID (from the Google Sheet URL between /d/ and /edit)
|
|
92
|
+
- range: Sheet range (e.g. "Sheet1", "Sheet1!A1:D10")
|
|
93
|
+
- values: 2D array of strings (required for write and append actions)
|
|
94
|
+
|
|
95
|
+
**Read example:**
|
|
96
|
+
\`\`\`json
|
|
97
|
+
{ "action": "read", "spreadsheet_id": "abc123", "range": "Sheet1!A1:D10" }
|
|
98
|
+
\`\`\`
|
|
99
|
+
Returns: { data: { values: [["row1col1", "row1col2"], ...] } }
|
|
100
|
+
|
|
101
|
+
**Write (overwrite) example:**
|
|
102
|
+
\`\`\`json
|
|
103
|
+
{ "action": "write", "spreadsheet_id": "abc123", "range": "Sheet1!A1:B2", "values": [["a","b"],["c","d"]] }
|
|
104
|
+
\`\`\`
|
|
105
|
+
Returns: { data: { updated_cells: 4 } }
|
|
106
|
+
|
|
107
|
+
**Append rows example:**
|
|
108
|
+
\`\`\`json
|
|
109
|
+
{ "action": "append", "spreadsheet_id": "abc123", "range": "Sheet1", "values": [["new","row"]] }
|
|
110
|
+
\`\`\`
|
|
111
|
+
Returns: { data: { updated_cells: 2 } }
|
|
112
|
+
|
|
113
|
+
**Important:** The append action auto-detects table boundaries and may place data in unexpected columns. For precise cell placement, use the "write" action with an explicit cell range (e.g. "Sheet1!D6") instead.
|
|
114
|
+
|
|
115
|
+
## Using curl via bash
|
|
116
|
+
|
|
117
|
+
You can also make these API calls using curl in the bash tool. The API key is available as \`$EMPIRICALRUN_API_KEY\` and the dashboard base URL is \`https://dash.empirical.run\` (or \`$DASHBOARD_DOMAIN\` if set).
|
|
118
|
+
|
|
119
|
+
Example - list files:
|
|
120
|
+
\`\`\`
|
|
121
|
+
curl -s -H "Authorization: Bearer $EMPIRICALRUN_API_KEY" "https://dash.empirical.run/api/files"
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
Example - download a file (use the signed \`url\` from a file response):
|
|
125
|
+
\`\`\`
|
|
126
|
+
curl -s -o output_file "<signed_url>"
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
This is especially useful for downloading files (via signed URLs) to the local filesystem for processing.
|
|
42
130
|
`,
|
|
43
131
|
parameters: APIClientSchema,
|
|
44
132
|
},
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { PendingToolCall, SupportedChatModels, Tool, ToolDefinition } from "@empiricalrun/shared-types/chat-agent";
|
|
2
|
-
import { ServicePayload } from "@empiricalrun/shared-types/tool-execute-service";
|
|
3
2
|
export { safeBashTool } from "./definitions/safe-bash";
|
|
4
3
|
export { scrapeHtmlTool } from "./firecrawl-scrape";
|
|
5
4
|
export { validateToolInput } from "./utils/validate-schema";
|
|
6
5
|
type ToolOrToolDefinition = Tool | ToolDefinition;
|
|
6
|
+
export declare const testGenerationToolsWithoutBrowserAgent: ToolOrToolDefinition[];
|
|
7
7
|
export declare const testGenerationTools: ToolOrToolDefinition[];
|
|
8
|
-
export declare const allToolsDefinitions: ToolOrToolDefinition[];
|
|
9
8
|
export declare function hasBuiltInTextEditor(model: SupportedChatModels): boolean;
|
|
10
9
|
export declare function hasBuiltInWebFetch(model: SupportedChatModels): boolean;
|
|
11
10
|
export declare function textEditorToolsForModel(model: SupportedChatModels): ToolOrToolDefinition[];
|
|
12
11
|
export declare function textViewToolsForModel(model: SupportedChatModels): ToolOrToolDefinition[];
|
|
13
12
|
export declare function toolsNeedBrowser(toolCalls: PendingToolCall[]): boolean;
|
|
14
13
|
export declare function nameForTelemetry(toolCall: PendingToolCall): string;
|
|
15
|
-
export declare function sendToolRequestToRemoteQueue(payload: ServicePayload): Promise<void>;
|
|
16
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,IAAI,EACJ,cAAc,EACf,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,IAAI,EACJ,cAAc,EACf,MAAM,uCAAuC,CAAC;AA+B/C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,KAAK,oBAAoB,GAAG,IAAI,GAAG,cAAc,CAAC;AAclD,eAAO,MAAM,sCAAsC,EAAE,oBAAoB,EAKxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBAAoB,EAGrD,CAAC;AAkBF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,WAE9D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,WAE5D;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,eAAe,EAAE,WAM5D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAQlE"}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.testGenerationTools = exports.testGenerationToolsWithoutBrowserAgent = exports.validateToolInput = exports.scrapeHtmlTool = exports.safeBashTool = void 0;
|
|
4
4
|
exports.hasBuiltInTextEditor = hasBuiltInTextEditor;
|
|
5
5
|
exports.hasBuiltInWebFetch = hasBuiltInWebFetch;
|
|
6
6
|
exports.textEditorToolsForModel = textEditorToolsForModel;
|
|
7
7
|
exports.textViewToolsForModel = textViewToolsForModel;
|
|
8
8
|
exports.toolsNeedBrowser = toolsNeedBrowser;
|
|
9
9
|
exports.nameForTelemetry = nameForTelemetry;
|
|
10
|
-
exports.sendToolRequestToRemoteQueue = sendToolRequestToRemoteQueue;
|
|
11
|
-
const SQSClient_1 = require("../utils/SQSClient");
|
|
12
10
|
const create_pull_request_1 = require("./create-pull-request");
|
|
13
11
|
const analyse_video_1 = require("./definitions/analyse-video");
|
|
14
12
|
const delete_file_1 = require("./definitions/delete-file");
|
|
@@ -30,7 +28,6 @@ const issues_v1_1 = require("./issues-v1");
|
|
|
30
28
|
const list_environments_1 = require("./list-environments");
|
|
31
29
|
const test_run_fetcher_1 = require("./test-run-fetcher");
|
|
32
30
|
const triage_summary_1 = require("./triage-summary");
|
|
33
|
-
const queue_1 = require("./utils/queue");
|
|
34
31
|
var safe_bash_2 = require("./definitions/safe-bash");
|
|
35
32
|
Object.defineProperty(exports, "safeBashTool", { enumerable: true, get: function () { return safe_bash_2.safeBashTool; } });
|
|
36
33
|
var firecrawl_scrape_2 = require("./firecrawl-scrape");
|
|
@@ -48,14 +45,17 @@ const commonTools = [
|
|
|
48
45
|
list_tests_and_projects_1.listProjectsTool,
|
|
49
46
|
list_tests_and_projects_1.listTestsForProjectTool,
|
|
50
47
|
];
|
|
51
|
-
exports.
|
|
52
|
-
test_gen_browser_1.generateTestWithBrowserAgent,
|
|
48
|
+
exports.testGenerationToolsWithoutBrowserAgent = [
|
|
53
49
|
create_pull_request_1.createPullRequestTool,
|
|
54
50
|
merge_conflicts_1.mergeConflictsTool,
|
|
55
51
|
delete_file_1.deleteFileTool,
|
|
56
52
|
rename_file_1.renameFileTool,
|
|
57
53
|
];
|
|
58
|
-
exports.
|
|
54
|
+
exports.testGenerationTools = [
|
|
55
|
+
test_gen_browser_1.generateTestWithBrowserAgent,
|
|
56
|
+
...exports.testGenerationToolsWithoutBrowserAgent,
|
|
57
|
+
];
|
|
58
|
+
const allToolsDefinitions = [
|
|
59
59
|
...commonTools,
|
|
60
60
|
...exports.testGenerationTools,
|
|
61
61
|
analyse_video_1.analyseVideo,
|
|
@@ -83,7 +83,7 @@ function textViewToolsForModel(model) {
|
|
|
83
83
|
return !hasBuiltInTextEditor(model) ? Object.values(str_replace_editor_1.textViewTools) : [];
|
|
84
84
|
}
|
|
85
85
|
function toolsNeedBrowser(toolCalls) {
|
|
86
|
-
return toolCalls.some((toolCall) =>
|
|
86
|
+
return toolCalls.some((toolCall) => allToolsDefinitions.find((t) => t.schema.name === toolCall.name)
|
|
87
87
|
?.needsBrowser);
|
|
88
88
|
}
|
|
89
89
|
function nameForTelemetry(toolCall) {
|
|
@@ -96,18 +96,3 @@ function nameForTelemetry(toolCall) {
|
|
|
96
96
|
return toolName;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
async function sendToolRequestToRemoteQueue(payload) {
|
|
100
|
-
const needsBrowser = toolsNeedBrowser(payload.toolCalls);
|
|
101
|
-
const queueUrl = (0, queue_1.getQueueUrl)(payload.toolCalls, needsBrowser);
|
|
102
|
-
if (!queueUrl) {
|
|
103
|
-
throw new Error(`queueUrl is required for remote execution.`);
|
|
104
|
-
}
|
|
105
|
-
const region = process.env.AWS_REGION;
|
|
106
|
-
const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
107
|
-
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
108
|
-
if (!region || !accessKeyId || !secretAccessKey) {
|
|
109
|
-
throw new Error("AWS_REGION, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY must be set");
|
|
110
|
-
}
|
|
111
|
-
const sqs = new SQSClient_1.SQSClient(region, accessKeyId, secretAccessKey);
|
|
112
|
-
await sqs.sendMessage(queueUrl, payload);
|
|
113
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/safe-bash/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/safe-bash/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,uCAAuC,CAAC;AAqN9E,eAAO,MAAM,YAAY,EAAE,IAmF1B,CAAC"}
|
|
@@ -7,6 +7,57 @@ const safe_bash_1 = require("../definitions/safe-bash");
|
|
|
7
7
|
const apply_line_limit_1 = require("../utils/apply-line-limit");
|
|
8
8
|
const validators_1 = require("../utils/validators");
|
|
9
9
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
10
|
+
function execWithProcessGroupTimeout(script, options) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const child = (0, child_process_1.spawn)("/bin/bash", ["-c", script], {
|
|
13
|
+
cwd: options.cwd,
|
|
14
|
+
env: options.env,
|
|
15
|
+
detached: true,
|
|
16
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
17
|
+
});
|
|
18
|
+
let stdout = "";
|
|
19
|
+
let stderr = "";
|
|
20
|
+
let killed = false;
|
|
21
|
+
child.stdout.on("data", (data) => {
|
|
22
|
+
stdout += data.toString();
|
|
23
|
+
});
|
|
24
|
+
child.stderr.on("data", (data) => {
|
|
25
|
+
stderr += data.toString();
|
|
26
|
+
});
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
killed = true;
|
|
29
|
+
// Kill the entire process group (negative pid)
|
|
30
|
+
try {
|
|
31
|
+
process.kill(-child.pid, "SIGKILL");
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Process group may already be gone
|
|
35
|
+
}
|
|
36
|
+
}, options.timeout);
|
|
37
|
+
child.on("close", (code) => {
|
|
38
|
+
clearTimeout(timer);
|
|
39
|
+
if (killed) {
|
|
40
|
+
const error = new Error("Process timed out");
|
|
41
|
+
error.stdout = stdout;
|
|
42
|
+
error.stderr = stderr || `Process timed out after ${options.timeout}ms`;
|
|
43
|
+
reject(error);
|
|
44
|
+
}
|
|
45
|
+
else if (code !== 0) {
|
|
46
|
+
const error = new Error(`Process exited with code ${code}`);
|
|
47
|
+
error.stdout = stdout;
|
|
48
|
+
error.stderr = stderr || `Process exited with code ${code}`;
|
|
49
|
+
reject(error);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
resolve({ stdout, stderr });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
child.on("error", (err) => {
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
reject(err);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
10
61
|
const DANGEROUS_PATTERNS = [
|
|
11
62
|
/git\s+checkout/i,
|
|
12
63
|
/git\s+switch/i,
|
|
@@ -111,10 +162,9 @@ exports.safeBashTool = {
|
|
|
111
162
|
let stdout = "";
|
|
112
163
|
let stderr = "";
|
|
113
164
|
try {
|
|
114
|
-
const result = await
|
|
165
|
+
const result = await execWithProcessGroupTimeout(script, {
|
|
115
166
|
cwd: repoPath,
|
|
116
167
|
timeout,
|
|
117
|
-
shell: "/bin/bash",
|
|
118
168
|
env: { ...process.env, ...environmentOverrides },
|
|
119
169
|
});
|
|
120
170
|
stdout = result.stdout;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/slack-message/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/slack-message/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uCAAuC,CAAC;AAuBlE,eAAO,MAAM,gBAAgB,EAAE,IAiD9B,CAAC"}
|
|
@@ -2,9 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.slackMessageTool = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const SlackActionSchema = zod_1.z.object({
|
|
6
|
+
label: zod_1.z.string().describe("Button label text"),
|
|
7
|
+
url: zod_1.z.string().describe("URL to open when clicked"),
|
|
8
|
+
style: zod_1.z
|
|
9
|
+
.enum(["primary", "danger"])
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Optional button style: primary (green) or danger (red)"),
|
|
12
|
+
});
|
|
5
13
|
const SlackMessageSchema = zod_1.z.object({
|
|
6
14
|
channel_id: zod_1.z.string().describe("Slack channel ID to post the message to"),
|
|
7
15
|
message: zod_1.z.string().describe("Message text to post"),
|
|
16
|
+
actions: zod_1.z
|
|
17
|
+
.array(SlackActionSchema)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Optional list of action buttons to include below the message. Each button opens a URL when clicked."),
|
|
8
20
|
});
|
|
9
21
|
exports.slackMessageTool = {
|
|
10
22
|
schema: {
|
|
@@ -39,6 +51,7 @@ Use this tool to send messages to Slack channels that are linked to the project.
|
|
|
39
51
|
body: {
|
|
40
52
|
channel_id: input.channel_id,
|
|
41
53
|
message: input.message,
|
|
54
|
+
actions: input.actions,
|
|
42
55
|
},
|
|
43
56
|
});
|
|
44
57
|
return {
|
|
@@ -49,23 +49,6 @@ type FailedRunMetadata = {
|
|
|
49
49
|
pw_test_id: string;
|
|
50
50
|
varying_retries: boolean;
|
|
51
51
|
};
|
|
52
|
-
type CapturedNetworkFailure = {
|
|
53
|
-
endpoint: string;
|
|
54
|
-
status: number;
|
|
55
|
-
timestamp: string;
|
|
56
|
-
distanceFromFailureInMilliseconds: number;
|
|
57
|
-
method: string;
|
|
58
|
-
request: {
|
|
59
|
-
headers: {
|
|
60
|
-
[any: string]: string;
|
|
61
|
-
}[];
|
|
62
|
-
};
|
|
63
|
-
response: {
|
|
64
|
-
headers: {
|
|
65
|
-
[any: string]: string;
|
|
66
|
-
}[];
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
52
|
type TestCaseSummaryDetail = {
|
|
70
53
|
id: number;
|
|
71
54
|
test_case_id: number;
|
|
@@ -75,26 +58,7 @@ type TestCaseSummaryDetail = {
|
|
|
75
58
|
failure_type: string;
|
|
76
59
|
failure_type_description: string;
|
|
77
60
|
last_commit_before_run_started_at: string;
|
|
78
|
-
merged_summary?: {
|
|
79
|
-
content: string;
|
|
80
|
-
} | null;
|
|
81
61
|
failed_run_metadata: FailedRunMetadata;
|
|
82
|
-
visual_diff_summary: {
|
|
83
|
-
failedStep: string;
|
|
84
|
-
reason: string;
|
|
85
|
-
summary: string;
|
|
86
|
-
videos_picked_for_comparison: {
|
|
87
|
-
failure: string;
|
|
88
|
-
success: string;
|
|
89
|
-
};
|
|
90
|
-
} | null;
|
|
91
|
-
error_stack_summary?: {
|
|
92
|
-
content: string;
|
|
93
|
-
} | null;
|
|
94
|
-
network_metadata: {
|
|
95
|
-
failed_calls: CapturedNetworkFailure[];
|
|
96
|
-
failed_calls_within_time_range: CapturedNetworkFailure[];
|
|
97
|
-
} | null;
|
|
98
62
|
created_at: string;
|
|
99
63
|
slug: string;
|
|
100
64
|
failing_line: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/types.ts"],"names":[],"mappings":"AACA,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,eAAe,GAAG,OAAO,GAAG;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/types.ts"],"names":[],"mappings":"AACA,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,eAAe,GAAG,OAAO,GAAG;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,EAAE,MAAM,CAAC;IACjC,iCAAiC,EAAE,MAAM,CAAC;IAC1C,mBAAmB,EAAE,iBAAiB,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE;QACJ,QAAQ,EAAE;YACR,OAAO,EAAE,OAAO,CAAC;YACjB,OAAO,EAAE,eAAe,CAAC;YACzB,uBAAuB,EAAE,qBAAqB,EAAE,CAAC;SAClD,CAAC;KACH,GAAG,IAAI,CAAC;IACT,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-gen",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"zod": "^4.0.1",
|
|
91
91
|
"@empiricalrun/ast-parser": "^0.0.10",
|
|
92
92
|
"@empiricalrun/cua": "^0.3.0",
|
|
93
|
-
"@empiricalrun/dashboard-client": "^0.
|
|
93
|
+
"@empiricalrun/dashboard-client": "^0.3.0",
|
|
94
94
|
"@empiricalrun/shared-types": "0.12.1",
|
|
95
95
|
"@empiricalrun/llm": "^0.26.0",
|
|
96
96
|
"@empiricalrun/r2-uploader": "^0.9.1",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"videostil": "0.3.5"
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@playwright/test": "1.
|
|
103
|
+
"@playwright/test": "1.58.2",
|
|
104
104
|
"@types/async-retry": "^1.4.8",
|
|
105
105
|
"@types/console-log-level": "^1.4.5",
|
|
106
106
|
"@types/detect-port": "^1.3.5",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"@types/pixelmatch": "^5.2.6",
|
|
114
114
|
"@types/serve-handler": "^6.1.4",
|
|
115
115
|
"js-levenshtein": "^1.1.6",
|
|
116
|
-
"playwright": "1.
|
|
116
|
+
"playwright": "1.58.2",
|
|
117
117
|
"serve-handler": "^6.1.6",
|
|
118
118
|
"ts-patch": "^3.3.0"
|
|
119
119
|
},
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/logger.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/cli.ts","./src/agent/index.ts","./src/agent/base/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/chat/prompt/test-case-def.ts","./src/agent/chat/prompt/trace-utils-docs.ts","./src/agent/code-review/index.ts","./src/agent/code-review/types.ts","./src/agent/code-review/xml-parser.ts","./src/agent/code-review/executor/index.ts","./src/agent/fast-triage/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/agent/triage/index.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/auth/cli-auth.ts","./src/auth/index.ts","./src/auth/token-store.ts","./src/bin/index.ts","./src/bin/setup.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/dashboard/client.ts","./src/dashboard/index.ts","./src/dashboard/tool-response-from-sandbox.ts","./src/dashboard/tool-response.ts","./src/dashboard/totp.ts","./src/dashboard/types.ts","./src/errors/index.ts","./src/file/client.ts","./src/file/server.ts","./src/file-info/index.ts","./src/file-info/adapters/file-system/index.ts","./src/file-info/adapters/file-system/reader.ts","./src/file-info/adapters/github/
|
|
1
|
+
{"root":["./src/index.ts","./src/logger.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/cli.ts","./src/agent/index.ts","./src/agent/base/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/chat/prompt/skills.ts","./src/agent/chat/prompt/test-case-def.ts","./src/agent/chat/prompt/trace-utils-docs.ts","./src/agent/code-review/index.ts","./src/agent/code-review/types.ts","./src/agent/code-review/xml-parser.ts","./src/agent/code-review/executor/index.ts","./src/agent/fast-triage/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/agent/triage/index.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/auth/cli-auth.ts","./src/auth/index.ts","./src/auth/token-store.ts","./src/bin/index.ts","./src/bin/setup.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/dashboard/client.ts","./src/dashboard/index.ts","./src/dashboard/tool-response-from-sandbox.ts","./src/dashboard/tool-response.ts","./src/dashboard/totp.ts","./src/dashboard/types.ts","./src/errors/index.ts","./src/file/client.ts","./src/file/server.ts","./src/file-info/index.ts","./src/file-info/adapters/file-system/index.ts","./src/file-info/adapters/file-system/reader.ts","./src/file-info/adapters/github/reader.ts","./src/generate-summary/frame-sampling.ts","./src/generate-summary/generate-error-stack-summary.ts","./src/generate-summary/generate-failed-step-screenshot-diff-summary.ts","./src/generate-summary/generate-grouped-summary.ts","./src/generate-summary/merge-summary.ts","./src/generate-summary/pick-videos-for-comparison.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/recorder/env-variables.ts","./src/recorder/index.ts","./src/recorder/request.ts","./src/recorder/temp-files.ts","./src/recorder/upload.ts","./src/recorder/validation.ts","./src/telemetry/index.ts","./src/test-build/index.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/index.ts","./src/tools/list-environments.ts","./src/tools/run-test.ts","./src/tools/test-gen-browser.ts","./src/tools/analyse-video/index.ts","./src/tools/api-client/index.ts","./src/tools/create-pull-request/index.ts","./src/tools/create-pull-request/utils.ts","./src/tools/definitions/analyse-video.ts","./src/tools/definitions/delete-file.ts","./src/tools/definitions/download-build.ts","./src/tools/definitions/grep.ts","./src/tools/definitions/list-tests-and-projects.ts","./src/tools/definitions/merge-conflicts.ts","./src/tools/definitions/publish-markdown-report.ts","./src/tools/definitions/rename-file.ts","./src/tools/definitions/run-test.ts","./src/tools/definitions/safe-bash.ts","./src/tools/definitions/str_replace_editor.ts","./src/tools/definitions/test-gen-browser.ts","./src/tools/definitions/trace-dot-zip.ts","./src/tools/definitions/utils.ts","./src/tools/delete-file/index.ts","./src/tools/download-build/index.ts","./src/tools/executor/base.ts","./src/tools/executor/index.ts","./src/tools/executor/types.ts","./src/tools/executor/utils/checkpoint.ts","./src/tools/executor/utils/git.ts","./src/tools/executor/utils/index.ts","./src/tools/executor/utils/pr-description.ts","./src/tools/fetch-file/index.ts","./src/tools/fetch-file/utils.ts","./src/tools/fetch-session-diff/index.ts","./src/tools/file-operations/create.ts","./src/tools/file-operations/index.ts","./src/tools/file-operations/insert.ts","./src/tools/file-operations/replace.ts","./src/tools/file-operations/shared/helpers.ts","./src/tools/file-operations/view/index.ts","./src/tools/firecrawl-scrape/index.ts","./src/tools/grep/index.ts","./src/tools/grep/types.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/issues-v1/index.ts","./src/tools/issues-v1/list-issues.ts","./src/tools/issues-v1/utils.ts","./src/tools/issues-v2/create-issue.ts","./src/tools/issues-v2/set-issue-description.ts","./src/tools/issues-v2/update-issue.ts","./src/tools/list-tests-and-projects/index.ts","./src/tools/merge-conflicts/index.ts","./src/tools/publish-markdown-report/index.ts","./src/tools/rename-file/index.ts","./src/tools/safe-bash/index.ts","./src/tools/slack-message/index.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/trace-dot-zip/index.ts","./src/tools/trace-dot-zip/types.ts","./src/tools/trace-dot-zip/utils/console-trace.ts","./src/tools/trace-dot-zip/utils/extract-screenshots.ts","./src/tools/trace-dot-zip/utils/extract-steps.ts","./src/tools/trace-dot-zip/utils/extract-zip.ts","./src/tools/trace-dot-zip/utils/network-trace.ts","./src/tools/triage-summary/index.ts","./src/tools/triage-summary/types.ts","./src/tools/triage-summary/utils.ts","./src/tools/utils/apply-line-limit.ts","./src/tools/utils/validate-schema.ts","./src/tools/utils/validators.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file.ts","./src/utils/hash.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/model.ts","./src/utils/playwright-test-id.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts","./src/utils/url-validation.ts","./src/utils/dedup/dedup-image.ts","./src/utils/dedup/find-threshold.ts","./src/video-core/index.ts","./src/video-core/model-limits.ts","./src/video-core/storage-manager.ts","./src/video-core/types.ts","./src/video-core/utils.ts"],"version":"5.8.3"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { IDashboardAPIClient } from "@empiricalrun/shared-types/api/base";
|
|
2
|
-
import { ToolResult } from "@empiricalrun/shared-types/chat-agent";
|
|
3
|
-
import { type StrReplaceInputParams } from "../../../tools/file-operations/shared/helpers";
|
|
4
|
-
export { getFileInfoFromGitHub } from "./reader";
|
|
5
|
-
export declare function viewFileUsingGitHub({ input, repoName, apiClient, branchName, baseBranch, }: {
|
|
6
|
-
input: StrReplaceInputParams;
|
|
7
|
-
repoName: string;
|
|
8
|
-
apiClient: IDashboardAPIClient;
|
|
9
|
-
branchName: string;
|
|
10
|
-
baseBranch: string;
|
|
11
|
-
}): Promise<ToolResult>;
|
|
12
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,+CAA+C,CAAC;AAGvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,wBAAsB,mBAAmB,CAAC,EACxC,KAAK,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,UAAU,GACX,EAAE;IACD,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CA2BtB"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFileInfoFromGitHub = void 0;
|
|
4
|
-
exports.viewFileUsingGitHub = viewFileUsingGitHub;
|
|
5
|
-
const helpers_1 = require("../../../tools/file-operations/shared/helpers");
|
|
6
|
-
const reader_1 = require("./reader");
|
|
7
|
-
var reader_2 = require("./reader");
|
|
8
|
-
Object.defineProperty(exports, "getFileInfoFromGitHub", { enumerable: true, get: function () { return reader_2.getFileInfoFromGitHub; } });
|
|
9
|
-
async function viewFileUsingGitHub({ input, repoName, apiClient, branchName, baseBranch, }) {
|
|
10
|
-
const filePath = (0, helpers_1.normalizePath)(input.path);
|
|
11
|
-
const githubReader = new reader_1.GitHubFileReader(repoName, apiClient);
|
|
12
|
-
const fileData = await githubReader.readFile(filePath, branchName, baseBranch);
|
|
13
|
-
if (!fileData) {
|
|
14
|
-
return {
|
|
15
|
-
result: `Error: File or directory ${filePath} is not found.`,
|
|
16
|
-
isError: true,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
if (fileData.isDirectory) {
|
|
20
|
-
return {
|
|
21
|
-
result: fileData.content,
|
|
22
|
-
isError: false,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return {
|
|
26
|
-
result: (0, helpers_1.formatLinesWithNumbers)(fileData.content, input.view_range),
|
|
27
|
-
isError: false,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { PendingToolCall } from "@empiricalrun/shared-types/chat-agent";
|
|
2
|
-
export declare function appendSuffixToQueueUrl(queueUrl: string, suffix: string): string;
|
|
3
|
-
export declare function replaceRegionInUrl(url: string, newRegion: string): string;
|
|
4
|
-
export declare function getQueueUrl(toolCalls: PendingToolCall[], needsBrowser: boolean): string;
|
|
5
|
-
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../src/tools/utils/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAExE,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAKR;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOzE;AAkBD,wBAAgB,WAAW,CACzB,SAAS,EAAE,eAAe,EAAE,EAC5B,YAAY,EAAE,OAAO,GACpB,MAAM,CAeR"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.appendSuffixToQueueUrl = appendSuffixToQueueUrl;
|
|
4
|
-
exports.replaceRegionInUrl = replaceRegionInUrl;
|
|
5
|
-
exports.getQueueUrl = getQueueUrl;
|
|
6
|
-
function appendSuffixToQueueUrl(queueUrl, suffix) {
|
|
7
|
-
const parts = queueUrl.split("/");
|
|
8
|
-
const queueName = parts.pop();
|
|
9
|
-
const queueNameWithoutFifo = queueName?.replace(/\.fifo$/, "");
|
|
10
|
-
return `${parts.join("/")}/${queueNameWithoutFifo}-${suffix}.fifo`;
|
|
11
|
-
}
|
|
12
|
-
function replaceRegionInUrl(url, newRegion) {
|
|
13
|
-
const parsedUrl = new URL(url);
|
|
14
|
-
parsedUrl.hostname = parsedUrl.hostname.replace(/\.([a-z0-9-]+)\.amazonaws\.com$/, `.${newRegion}.amazonaws.com`);
|
|
15
|
-
return parsedUrl.toString();
|
|
16
|
-
}
|
|
17
|
-
function buildQueueUrlsForPreview(baseQueueUrl) {
|
|
18
|
-
const buildHash = process.env.TOOL_EXECUTION_SERVICE_BUILD_HASH;
|
|
19
|
-
if (!buildHash) {
|
|
20
|
-
throw new Error("TOOL_EXECUTION_SERVICE_BUILD_HASH is not set");
|
|
21
|
-
}
|
|
22
|
-
const updatedRegionForQueue = replaceRegionInUrl(baseQueueUrl, process.env.AWS_REGION);
|
|
23
|
-
const queueUrl = appendSuffixToQueueUrl(updatedRegionForQueue, buildHash);
|
|
24
|
-
console.log("queueUrl for preview", queueUrl);
|
|
25
|
-
return queueUrl;
|
|
26
|
-
}
|
|
27
|
-
function getQueueUrl(toolCalls, needsBrowser) {
|
|
28
|
-
const browserSqsQueueUrl = process.env.TOOL_EXECUTION_SQS_URL_BROWSER;
|
|
29
|
-
const baseSqsQueueUrl = process.env.TOOL_EXECUTION_SQS_URL;
|
|
30
|
-
const queueUrl = needsBrowser ? browserSqsQueueUrl : baseSqsQueueUrl;
|
|
31
|
-
if (!queueUrl) {
|
|
32
|
-
throw new Error("No queue URL found");
|
|
33
|
-
}
|
|
34
|
-
const vercelEnv = process.env.VERCEL_ENV || "";
|
|
35
|
-
if (vercelEnv !== "preview") {
|
|
36
|
-
return queueUrl;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
return buildQueueUrlsForPreview(queueUrl);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ServicePayload } from "@empiricalrun/shared-types/tool-execute-service";
|
|
2
|
-
export declare class SQSClient {
|
|
3
|
-
private region;
|
|
4
|
-
private accessKeyId;
|
|
5
|
-
private secretAccessKey;
|
|
6
|
-
private sessionToken?;
|
|
7
|
-
constructor(region: string, accessKeyId: string, secretAccessKey: string, sessionToken?: string);
|
|
8
|
-
private sha256;
|
|
9
|
-
private hmacSha256;
|
|
10
|
-
private getSignatureKey;
|
|
11
|
-
private sign;
|
|
12
|
-
sendMessage(queueUrl: string, payload: ServicePayload): Promise<void>;
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=SQSClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SQSClient.d.ts","sourceRoot":"","sources":["../../src/utils/SQSClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AAEjF,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAC,CAAS;gBAG5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,MAAM;YAQT,MAAM;YAON,UAAU;YAkBV,eAAe;YAgBf,IAAI;IASZ,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAyG5E"}
|
package/dist/utils/SQSClient.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SQSClient = void 0;
|
|
4
|
-
class SQSClient {
|
|
5
|
-
region;
|
|
6
|
-
accessKeyId;
|
|
7
|
-
secretAccessKey;
|
|
8
|
-
sessionToken;
|
|
9
|
-
constructor(region, accessKeyId, secretAccessKey, sessionToken) {
|
|
10
|
-
this.region = region;
|
|
11
|
-
this.accessKeyId = accessKeyId;
|
|
12
|
-
this.secretAccessKey = secretAccessKey;
|
|
13
|
-
this.sessionToken = sessionToken;
|
|
14
|
-
}
|
|
15
|
-
async sha256(message) {
|
|
16
|
-
const msgBuffer = new TextEncoder().encode(message);
|
|
17
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
|
|
18
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
19
|
-
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
20
|
-
}
|
|
21
|
-
async hmacSha256(key, message) {
|
|
22
|
-
const cryptoKey = await crypto.subtle.importKey("raw", key, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
23
|
-
return await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(message));
|
|
24
|
-
}
|
|
25
|
-
async getSignatureKey(key, dateStamp, regionName, serviceName) {
|
|
26
|
-
const kDate = await this.hmacSha256(new TextEncoder().encode("AWS4" + key), dateStamp);
|
|
27
|
-
const kRegion = await this.hmacSha256(kDate, regionName);
|
|
28
|
-
const kService = await this.hmacSha256(kRegion, serviceName);
|
|
29
|
-
const kSigning = await this.hmacSha256(kService, "aws4_request");
|
|
30
|
-
return kSigning;
|
|
31
|
-
}
|
|
32
|
-
async sign(stringToSign, signingKey) {
|
|
33
|
-
const signature = await this.hmacSha256(signingKey, stringToSign);
|
|
34
|
-
const signatureArray = Array.from(new Uint8Array(signature));
|
|
35
|
-
return signatureArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
36
|
-
}
|
|
37
|
-
async sendMessage(queueUrl, payload) {
|
|
38
|
-
try {
|
|
39
|
-
const url = new URL(queueUrl);
|
|
40
|
-
const host = url.hostname;
|
|
41
|
-
const canonicalUri = url.pathname;
|
|
42
|
-
const now = new Date();
|
|
43
|
-
// The following two operations generate AWS-compliant timestamps:
|
|
44
|
-
// - amzDate: The full ISO8601 timestamp (without milliseconds and with no separators), used for the x-amz-date header.
|
|
45
|
-
// - dateStamp: The date portion (YYYYMMDD), used in the credential scope for AWS Signature V4.
|
|
46
|
-
const amzDate = now
|
|
47
|
-
.toISOString()
|
|
48
|
-
.replace(/\.\d{3}Z$/, "Z")
|
|
49
|
-
.replace(/[:-]/g, "");
|
|
50
|
-
const dateStamp = amzDate.slice(0, 8);
|
|
51
|
-
const method = "POST";
|
|
52
|
-
const service = "sqs";
|
|
53
|
-
const algorithm = "AWS4-HMAC-SHA256";
|
|
54
|
-
const credentialScope = `${dateStamp}/${this.region}/${service}/aws4_request`;
|
|
55
|
-
const messageBody = {
|
|
56
|
-
Action: "SendMessage",
|
|
57
|
-
Version: "2012-11-05",
|
|
58
|
-
QueueUrl: queueUrl,
|
|
59
|
-
MessageBody: JSON.stringify(payload),
|
|
60
|
-
MessageGroupId: payload.requestId,
|
|
61
|
-
MessageDeduplicationId: payload.requestId,
|
|
62
|
-
};
|
|
63
|
-
const body = Object.entries(messageBody)
|
|
64
|
-
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
65
|
-
.join("&");
|
|
66
|
-
const payloadHash = await this.sha256(body);
|
|
67
|
-
const canonicalHeaders = [
|
|
68
|
-
`host:${host}`,
|
|
69
|
-
`x-amz-date:${amzDate}`,
|
|
70
|
-
"",
|
|
71
|
-
].join("\n");
|
|
72
|
-
const signedHeaders = "host;x-amz-date";
|
|
73
|
-
const canonicalRequest = [
|
|
74
|
-
method,
|
|
75
|
-
canonicalUri,
|
|
76
|
-
"",
|
|
77
|
-
canonicalHeaders,
|
|
78
|
-
signedHeaders,
|
|
79
|
-
payloadHash,
|
|
80
|
-
].join("\n");
|
|
81
|
-
const stringToSign = [
|
|
82
|
-
algorithm,
|
|
83
|
-
amzDate,
|
|
84
|
-
credentialScope,
|
|
85
|
-
await this.sha256(canonicalRequest),
|
|
86
|
-
].join("\n");
|
|
87
|
-
const signingKey = await this.getSignatureKey(this.secretAccessKey, dateStamp, this.region, service);
|
|
88
|
-
const signature = await this.sign(stringToSign, signingKey);
|
|
89
|
-
const authorizationHeader = `${algorithm} Credential=${this.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
|
|
90
|
-
const headers = {
|
|
91
|
-
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
|
|
92
|
-
Host: host,
|
|
93
|
-
"X-Amz-Date": amzDate,
|
|
94
|
-
Authorization: authorizationHeader,
|
|
95
|
-
};
|
|
96
|
-
if (this.sessionToken) {
|
|
97
|
-
headers["X-Amz-Security-Token"] = this.sessionToken;
|
|
98
|
-
}
|
|
99
|
-
const response = await fetch(queueUrl, {
|
|
100
|
-
method: "POST",
|
|
101
|
-
headers,
|
|
102
|
-
body: body,
|
|
103
|
-
});
|
|
104
|
-
if (!response.ok) {
|
|
105
|
-
const errorText = await response.text();
|
|
106
|
-
console.error(`[SQSClient.sendMessage] SQS request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
107
|
-
throw new Error(`SQS request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
console.error("[SQSClient.sendMessage] Error:", err instanceof Error ? err.stack || err.message : err);
|
|
112
|
-
throw err;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
exports.SQSClient = SQSClient;
|