@empiricalrun/test-gen 0.74.2 → 0.76.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 +37 -0
- package/dist/agent/base/index.d.ts +43 -0
- package/dist/agent/base/index.d.ts.map +1 -0
- package/dist/agent/base/index.js +106 -0
- package/dist/agent/chat/agent-loop.d.ts +7 -7
- package/dist/agent/chat/agent-loop.d.ts.map +1 -1
- package/dist/agent/chat/agent-loop.js +5 -18
- package/dist/agent/chat/exports.d.ts +6 -4
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +9 -8
- 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 +130 -200
- package/dist/agent/chat/prompt/index.d.ts +5 -4
- package/dist/agent/chat/prompt/index.d.ts.map +1 -1
- package/dist/agent/chat/prompt/index.js +79 -68
- package/dist/agent/chat/state.d.ts +3 -5
- package/dist/agent/chat/state.d.ts.map +1 -1
- package/dist/agent/chat/state.js +2 -10
- package/dist/agent/chat/utils.d.ts +2 -4
- package/dist/agent/chat/utils.d.ts.map +1 -1
- package/dist/agent/chat/utils.js +2 -16
- package/dist/agent/cli.d.ts +11 -0
- package/dist/agent/cli.d.ts.map +1 -0
- package/dist/agent/cli.js +209 -0
- package/dist/agent/code-review/index.d.ts +7 -0
- package/dist/agent/code-review/index.d.ts.map +1 -0
- package/dist/agent/code-review/index.js +65 -0
- package/dist/agent/code-review/prompt.d.ts +1 -1
- package/dist/agent/code-review/prompt.d.ts.map +1 -1
- package/dist/agent/code-review/prompt.js +52 -16
- 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 +102 -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 +35 -0
- package/dist/bin/index.js +6 -6
- package/dist/file-info/adapters/github/index.d.ts +2 -2
- package/dist/file-info/adapters/github/index.d.ts.map +1 -1
- package/dist/file-info/adapters/github/index.js +4 -4
- package/dist/file-info/adapters/github/reader.d.ts +5 -10
- package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
- package/dist/file-info/adapters/github/reader.js +168 -138
- 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} +30 -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/extract-frames-from-video.d.ts +39 -0
- package/dist/tools/definitions/extract-frames-from-video.d.ts.map +1 -0
- package/dist/tools/definitions/extract-frames-from-video.js +60 -0
- package/dist/tools/definitions/fetch-video-analysis.d.ts +28 -0
- package/dist/tools/definitions/fetch-video-analysis.d.ts.map +1 -1
- package/dist/tools/definitions/fetch-video-analysis.js +39 -4
- package/dist/tools/definitions/rename-file.d.ts +3 -0
- package/dist/tools/definitions/rename-file.d.ts.map +1 -0
- package/dist/tools/definitions/rename-file.js +23 -0
- package/dist/tools/delete-file/index.d.ts.map +1 -1
- package/dist/tools/delete-file/index.js +13 -1
- package/dist/tools/executor/index.d.ts +1 -1
- package/dist/tools/executor/index.d.ts.map +1 -1
- package/dist/tools/executor/index.js +22 -7
- package/dist/tools/executor/utils/checkpoint.d.ts +1 -3
- package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -1
- package/dist/tools/executor/utils/checkpoint.js +17 -17
- package/dist/tools/executor/utils/git.d.ts +9 -1
- package/dist/tools/executor/utils/git.d.ts.map +1 -1
- package/dist/tools/executor/utils/git.js +72 -2
- package/dist/tools/extract-frames-from-video/index.d.ts +7 -0
- package/dist/tools/extract-frames-from-video/index.d.ts.map +1 -0
- package/dist/tools/extract-frames-from-video/index.js +145 -0
- package/dist/tools/{fetch-image → fetch-file}/index.d.ts +2 -2
- package/dist/tools/fetch-file/index.d.ts.map +1 -0
- package/dist/tools/fetch-file/index.js +97 -0
- 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/fetch-video-analysis/index.d.ts +3 -3
- package/dist/tools/fetch-video-analysis/index.d.ts.map +1 -1
- package/dist/tools/fetch-video-analysis/index.js +84 -24
- package/dist/tools/fetch-video-analysis/open-ai.d.ts +6 -0
- package/dist/tools/fetch-video-analysis/open-ai.d.ts.map +1 -0
- package/dist/tools/fetch-video-analysis/open-ai.js +37 -0
- package/dist/tools/fetch-video-analysis/utils.d.ts +9 -3
- package/dist/tools/fetch-video-analysis/utils.d.ts.map +1 -1
- package/dist/tools/fetch-video-analysis/utils.js +64 -15
- package/dist/tools/fetch-video-analysis/video-analysis.d.ts +2 -2
- package/dist/tools/fetch-video-analysis/video-analysis.d.ts.map +1 -1
- package/dist/tools/fetch-video-analysis/video-analysis.js +24 -8
- package/dist/tools/file-operations/create.d.ts.map +1 -1
- package/dist/tools/file-operations/create.js +6 -3
- package/dist/tools/file-operations/insert.d.ts.map +1 -1
- package/dist/tools/file-operations/insert.js +6 -3
- package/dist/tools/file-operations/replace.d.ts.map +1 -1
- package/dist/tools/file-operations/replace.js +6 -3
- package/dist/tools/file-operations/shared/git-helper.d.ts.map +1 -1
- package/dist/tools/file-operations/shared/git-helper.js +1 -1
- package/dist/tools/file-operations/view/index.d.ts +2 -5
- package/dist/tools/file-operations/view/index.d.ts.map +1 -1
- package/dist/tools/file-operations/view/index.js +2 -22
- package/dist/tools/index.d.ts +28 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +50 -22
- package/dist/tools/issues/update-issue.d.ts.map +1 -1
- package/dist/tools/issues/update-issue.js +16 -9
- package/dist/tools/merge-conflicts/index.js +1 -1
- package/dist/tools/rename-file/index.d.ts +3 -0
- package/dist/tools/rename-file/index.d.ts.map +1 -0
- package/dist/tools/rename-file/index.js +88 -0
- 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 +103 -0
- package/dist/tools/run-test.js +2 -2
- 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/trace-dot-zip/index.d.ts.map +1 -1
- package/dist/tools/trace-dot-zip/index.js +2 -1
- package/dist/tools/trace-dot-zip/types.d.ts +35 -3
- package/dist/tools/trace-dot-zip/types.d.ts.map +1 -1
- package/dist/tools/trace-dot-zip/utils/network-trace.d.ts +7 -2
- package/dist/tools/trace-dot-zip/utils/network-trace.d.ts.map +1 -1
- package/dist/tools/trace-dot-zip/utils/network-trace.js +130 -10
- package/dist/tools/upgrade-packages/index.js +1 -1
- 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/file.d.ts +1 -0
- package/dist/utils/file.d.ts.map +1 -1
- package/dist/utils/file.js +45 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -3
- package/dist/utils/local-ffmpeg-client.d.ts +27 -0
- package/dist/utils/local-ffmpeg-client.d.ts.map +1 -0
- package/dist/{tools/fetch-video-analysis → utils}/local-ffmpeg-client.js +117 -27
- package/package.json +5 -5
- package/tsconfig.tsbuildinfo +1 -1
- 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/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/fetch-image/index.d.ts.map +0 -1
- package/dist/tools/fetch-image/index.js +0 -63
- package/dist/tools/fetch-video-analysis/local-ffmpeg-client.d.ts +0 -24
- package/dist/tools/fetch-video-analysis/local-ffmpeg-client.d.ts.map +0 -1
- /package/dist/tools/{commit-and-create-pr → create-pull-request}/index.d.ts +0 -0
package/dist/bin/index.js
CHANGED
|
@@ -7,8 +7,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
8
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const chat_1 = require("../agent/chat");
|
|
11
10
|
const models_1 = require("../agent/chat/models");
|
|
11
|
+
const cli_1 = require("../agent/cli");
|
|
12
12
|
const auth_1 = require("../auth");
|
|
13
13
|
const client_1 = require("../dashboard/client");
|
|
14
14
|
const recorder_1 = require("../recorder");
|
|
@@ -20,13 +20,13 @@ const utils_1 = require("./utils");
|
|
|
20
20
|
dotenv_1.default.config({
|
|
21
21
|
path: [".env.local", ".env"],
|
|
22
22
|
});
|
|
23
|
-
async function runChatAgent({ modelInput, useDiskForChatState, prompt: initialPromptContent,
|
|
23
|
+
async function runChatAgent({ modelInput, useDiskForChatState, prompt: initialPromptContent, agentMode = "chat", resetChat, useFSCache, }) {
|
|
24
24
|
const resolvedModel = (0, models_1.resolveChatModelBasedOnInput)(modelInput);
|
|
25
|
-
return await (0,
|
|
25
|
+
return await (0, cli_1.runChatAgentForCLI)({
|
|
26
26
|
selectedModel: resolvedModel,
|
|
27
27
|
useDiskForChatState: useDiskForChatState || false,
|
|
28
28
|
initialPromptContent,
|
|
29
|
-
|
|
29
|
+
agentMode,
|
|
30
30
|
resetChat: resetChat || false,
|
|
31
31
|
useFSCache: useFSCache || false,
|
|
32
32
|
});
|
|
@@ -178,7 +178,7 @@ async function main() {
|
|
|
178
178
|
.option("--model <model>", "LLM to use (gpt-5, claude-4 or gemini-2.5)")
|
|
179
179
|
.option("--use-disk", "Save and load chat state from disk")
|
|
180
180
|
.option("--prompt <string>", "String to pass as user prompt")
|
|
181
|
-
.option("--
|
|
181
|
+
.option("--agent-mode <mode>", "Mode of the agent: 'chat' or 'triage' or 'video' or 'code-review' (Defaults to 'chat')")
|
|
182
182
|
.option("--use-cache", "Use filesystem cache for LLM responses (Claude-only, and will disable streaming)")
|
|
183
183
|
.option("--reset-chat", "Clear any saved chat state (last-chat.json) before starting")
|
|
184
184
|
.action(async (options) => {
|
|
@@ -186,7 +186,7 @@ async function main() {
|
|
|
186
186
|
modelInput: options.model,
|
|
187
187
|
useDiskForChatState: options.useDisk,
|
|
188
188
|
prompt: options.prompt,
|
|
189
|
-
|
|
189
|
+
agentMode: options.agentMode,
|
|
190
190
|
resetChat: options.resetChat,
|
|
191
191
|
useFSCache: options.useCache,
|
|
192
192
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { IDashboardAPIClient, ToolResult } from "@empiricalrun/shared-types";
|
|
2
2
|
import { type StrReplaceInputParams } from "../../../tools/file-operations/shared/helpers";
|
|
3
3
|
export { getFileInfoFromGitHub } from "./reader";
|
|
4
|
-
export declare function viewFileUsingGitHub({ input,
|
|
4
|
+
export declare function viewFileUsingGitHub({ input, repoName, apiClient, branchName, baseBranch, }: {
|
|
5
5
|
input: StrReplaceInputParams;
|
|
6
|
-
filePath: string;
|
|
7
6
|
repoName: string;
|
|
8
7
|
apiClient: IDashboardAPIClient;
|
|
9
8
|
branchName: string;
|
|
9
|
+
baseBranch: string;
|
|
10
10
|
}): Promise<ToolResult>;
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,+CAA+C,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,+CAA+C,CAAC;AAEvD,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"}
|
|
@@ -6,10 +6,10 @@ const helpers_1 = require("../../../tools/file-operations/shared/helpers");
|
|
|
6
6
|
const reader_1 = require("./reader");
|
|
7
7
|
var reader_2 = require("./reader");
|
|
8
8
|
Object.defineProperty(exports, "getFileInfoFromGitHub", { enumerable: true, get: function () { return reader_2.getFileInfoFromGitHub; } });
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const githubReader = new reader_1.GitHubFileReader(repoName, apiClient
|
|
12
|
-
const fileData = await githubReader.readFile(filePath, branchName);
|
|
9
|
+
async function viewFileUsingGitHub({ input, repoName, apiClient, branchName, baseBranch, }) {
|
|
10
|
+
const filePath = input.path;
|
|
11
|
+
const githubReader = new reader_1.GitHubFileReader(repoName, apiClient);
|
|
12
|
+
const fileData = await githubReader.readFile(filePath, branchName, baseBranch);
|
|
13
13
|
if (!fileData) {
|
|
14
14
|
return {
|
|
15
15
|
result: `Error: File or directory ${filePath} is not found.`,
|
|
@@ -2,15 +2,10 @@ import { FileInfo, FileReadResult, IDashboardAPIClient } from "@empiricalrun/sha
|
|
|
2
2
|
export declare class GitHubFileReader {
|
|
3
3
|
private repoName;
|
|
4
4
|
private apiClient;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
private
|
|
9
|
-
private resolveBranchName;
|
|
10
|
-
readFile(filePath: string, branchName: string): Promise<FileReadResult | null>;
|
|
11
|
-
private getFileContent;
|
|
12
|
-
private getContentsForDirectory;
|
|
13
|
-
getFileInfo(branchName: string): Promise<FileInfo>;
|
|
5
|
+
constructor(repoName: string, apiClient: IDashboardAPIClient);
|
|
6
|
+
resolveBranchName(branchName: string | undefined, baseBranch?: string): Promise<string>;
|
|
7
|
+
readFile(filePath: string, branchName: string, baseBranch: string): Promise<FileReadResult | null>;
|
|
8
|
+
private readDirectory;
|
|
14
9
|
}
|
|
15
|
-
export declare function getFileInfoFromGitHub(repoName: string, apiClient: IDashboardAPIClient, branchName: string): Promise<FileInfo>;
|
|
10
|
+
export declare function getFileInfoFromGitHub(repoName: string, apiClient: IDashboardAPIClient, branchName: string, baseBranchName: string): Promise<FileInfo>;
|
|
16
11
|
//# 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,EACL,QAAQ,EACR,cAAc,EACd,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/github/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,cAAc,EACd,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAcpC,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;gBADT,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,mBAAmB;IAGlC,iBAAiB,CACrB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,UAAU,GAAE,MAAe,GAC1B,OAAO,CAAC,MAAM,CAAC;IAsBZ,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YA4CnB,aAAa;CA8C5B;AAyED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC,CAyFnB"}
|
|
@@ -6,180 +6,210 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.GitHubFileReader = void 0;
|
|
7
7
|
exports.getFileInfoFromGitHub = getFileInfoFromGitHub;
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const dashboard_1 = require("../../../dashboard");
|
|
10
|
-
const REPO_OWNER = "empirical-run";
|
|
11
9
|
class GitHubFileReader {
|
|
12
10
|
repoName;
|
|
13
11
|
apiClient;
|
|
14
|
-
|
|
15
|
-
constructor(repoName, apiClient, repoOwner) {
|
|
12
|
+
constructor(repoName, apiClient) {
|
|
16
13
|
this.repoName = repoName;
|
|
17
14
|
this.apiClient = apiClient;
|
|
18
|
-
this.repoOwner = repoOwner;
|
|
19
15
|
}
|
|
20
|
-
async
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
url: `/repos/${this.repoOwner}/${this.repoName}/contents/${filePath}?ref=${branch}`,
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
|
-
async fetchTreeFromGitHub(branch) {
|
|
27
|
-
return (await this.apiClient.callGitHubProxy({
|
|
28
|
-
method: "GET",
|
|
29
|
-
url: `/repos/${this.repoOwner}/${this.repoName}/git/trees/${branch}?recursive=1`,
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
async resolveBranchName(branchName) {
|
|
33
|
-
if (!branchName || branchName === "main") {
|
|
34
|
-
return "main";
|
|
16
|
+
async resolveBranchName(branchName, baseBranch = "main") {
|
|
17
|
+
if (!branchName || branchName === baseBranch) {
|
|
18
|
+
return baseBranch;
|
|
35
19
|
}
|
|
36
20
|
try {
|
|
37
|
-
// Try to fetch the branch to see if it exists
|
|
21
|
+
// Try to fetch the branch to see if it exists via GitHub proxy
|
|
38
22
|
await this.apiClient.callGitHubProxy({
|
|
39
23
|
method: "GET",
|
|
40
|
-
url: `/repos/${this.
|
|
24
|
+
url: `/repos/empirical-run/${this.repoName}/branches/${branchName}`,
|
|
41
25
|
});
|
|
26
|
+
console.log(`[GitHubFileReader] Branch ${branchName} exists`);
|
|
42
27
|
return branchName;
|
|
43
28
|
}
|
|
44
29
|
catch {
|
|
45
|
-
// Branch doesn't exist, fallback to
|
|
46
|
-
|
|
30
|
+
// Branch doesn't exist, fallback to base branch
|
|
31
|
+
console.log(`[GitHubFileReader] Branch ${branchName} not found, falling back to ${baseBranch}`);
|
|
32
|
+
return baseBranch;
|
|
47
33
|
}
|
|
48
34
|
}
|
|
49
|
-
async readFile(filePath, branchName) {
|
|
50
|
-
const
|
|
51
|
-
|
|
35
|
+
async readFile(filePath, branchName, baseBranch) {
|
|
36
|
+
const resolvedBranch = await this.resolveBranchName(branchName, baseBranch);
|
|
37
|
+
// Check if path has file extension - if not, treat as directory
|
|
38
|
+
const hasFileExtension = path_1.default.extname(filePath) !== "";
|
|
39
|
+
if (!hasFileExtension) {
|
|
40
|
+
console.log(`[GitHubFileReader] Reading as directory: ${filePath}`);
|
|
41
|
+
return this.readDirectory(filePath, resolvedBranch);
|
|
42
|
+
}
|
|
52
43
|
try {
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
else {
|
|
44
|
+
console.log(`[GitHubFileReader] Reading as file: ${filePath}, resolved branch: ${resolvedBranch}`);
|
|
45
|
+
const params = {
|
|
46
|
+
repo: this.repoName,
|
|
47
|
+
path: filePath,
|
|
48
|
+
ref: resolvedBranch,
|
|
49
|
+
};
|
|
50
|
+
const response = await this.apiClient.request(`/api/github/files`, {
|
|
51
|
+
method: "GET",
|
|
52
|
+
params,
|
|
53
|
+
});
|
|
54
|
+
if (response.data?.fileContents.available) {
|
|
65
55
|
return {
|
|
66
|
-
content: response.
|
|
67
|
-
isDirectory:
|
|
56
|
+
content: response.data.fileContents.content,
|
|
57
|
+
isDirectory: false,
|
|
68
58
|
};
|
|
69
59
|
}
|
|
60
|
+
console.log(`[GitHubFileReader] File not available: ${filePath}`);
|
|
61
|
+
// For file paths (with extensions), don't fall back to directory reading
|
|
62
|
+
return null;
|
|
70
63
|
}
|
|
71
64
|
catch (error) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
throw error; // Re-throw other errors
|
|
65
|
+
console.log(`[GitHubFileReader] Error reading file ${filePath}:`, error);
|
|
66
|
+
// For file paths, return null (file not found)
|
|
67
|
+
return null;
|
|
76
68
|
}
|
|
77
|
-
return null;
|
|
78
69
|
}
|
|
79
|
-
async
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
async readDirectory(filePath, resolvedBranch) {
|
|
71
|
+
try {
|
|
72
|
+
console.log(`[GitHubFileReader] Reading directory: ${filePath}, resolved branch: ${resolvedBranch}`);
|
|
73
|
+
const params = {
|
|
74
|
+
repo: this.repoName,
|
|
75
|
+
path: filePath || ".", // Handle empty path
|
|
76
|
+
ref: resolvedBranch,
|
|
77
|
+
};
|
|
78
|
+
const treeResponse = await this.apiClient.request(`/api/github/tree`, {
|
|
79
|
+
method: "GET",
|
|
80
|
+
params,
|
|
81
|
+
});
|
|
82
|
+
if (treeResponse.data?.tree) {
|
|
83
|
+
const targetPath = filePath === "." || filePath === "" ? "" : filePath;
|
|
84
|
+
const files = treeResponse.data.tree.tree
|
|
85
|
+
.map((item) => item.path)
|
|
86
|
+
.filter((itemPath) => {
|
|
87
|
+
if (!itemPath)
|
|
88
|
+
return false;
|
|
89
|
+
// Check if item is a direct child of the target directory
|
|
90
|
+
const itemDir = path_1.default.dirname(itemPath);
|
|
91
|
+
// Normalize "." to "" for root directory comparison
|
|
92
|
+
const normalizedItemDir = itemDir === "." ? "" : itemDir;
|
|
93
|
+
return normalizedItemDir === targetPath;
|
|
94
|
+
})
|
|
95
|
+
.map((itemPath) => path_1.default.basename(itemPath))
|
|
96
|
+
.sort()
|
|
97
|
+
.join("\n");
|
|
98
|
+
return { content: files, isDirectory: true };
|
|
99
|
+
}
|
|
85
100
|
}
|
|
86
|
-
|
|
87
|
-
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.log(`[GitHubFileReader] Error reading directory ${filePath}:`, error);
|
|
88
103
|
}
|
|
89
|
-
|
|
104
|
+
return null;
|
|
90
105
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
}
|
|
107
|
+
exports.GitHubFileReader = GitHubFileReader;
|
|
108
|
+
async function getFileContent(repoName, path, apiClient, branchName) {
|
|
109
|
+
const params = {
|
|
110
|
+
repo: repoName,
|
|
111
|
+
path: path,
|
|
112
|
+
};
|
|
113
|
+
if (branchName) {
|
|
114
|
+
params.ref = branchName;
|
|
115
|
+
}
|
|
116
|
+
const response = await apiClient.request(`/api/github/files`, {
|
|
117
|
+
method: "GET",
|
|
118
|
+
params,
|
|
119
|
+
});
|
|
120
|
+
if (!response.data) {
|
|
121
|
+
throw new Error(`Unable to fetch file for FileInfo`);
|
|
122
|
+
}
|
|
123
|
+
return response.data.fileContents.content;
|
|
124
|
+
}
|
|
125
|
+
async function getContentsForDirectory({ repo, path, }, apiClient, branchName) {
|
|
126
|
+
const params = {
|
|
127
|
+
repo: repo,
|
|
128
|
+
path: path,
|
|
129
|
+
};
|
|
130
|
+
if (branchName) {
|
|
131
|
+
params.ref = branchName;
|
|
132
|
+
}
|
|
133
|
+
const response = await apiClient.request(`/api/github/tree`, {
|
|
134
|
+
method: "GET",
|
|
135
|
+
params,
|
|
136
|
+
});
|
|
137
|
+
if (!response.data) {
|
|
138
|
+
throw new Error(`Unable to fetch file for FileInfo`);
|
|
139
|
+
}
|
|
140
|
+
return response.data.tree;
|
|
141
|
+
}
|
|
142
|
+
async function getFileInfoFromGitHub(repoName, apiClient, branchName, baseBranchName) {
|
|
143
|
+
// Use GitHubFileReader to resolve the branch
|
|
144
|
+
const fileReader = new GitHubFileReader(repoName, apiClient);
|
|
145
|
+
const resolvedBranch = await fileReader.resolveBranchName(branchName, baseBranchName);
|
|
146
|
+
const files = await getContentsForDirectory({ repo: repoName, path: "" }, apiClient, resolvedBranch);
|
|
147
|
+
const root = [];
|
|
148
|
+
const nodeMap = {};
|
|
149
|
+
if (!files) {
|
|
150
|
+
return {
|
|
151
|
+
type: "directory",
|
|
152
|
+
path: repoName,
|
|
153
|
+
name: repoName,
|
|
154
|
+
children: [],
|
|
155
|
+
};
|
|
108
156
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
157
|
+
files.tree.forEach((file) => {
|
|
158
|
+
if (!file.path) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const pathParts = file.path.split("/");
|
|
162
|
+
const fileName = path_1.default.basename(file.path);
|
|
163
|
+
const isFile = file.type === "blob";
|
|
164
|
+
const currentPath = file.path;
|
|
165
|
+
const currentNode = isFile
|
|
166
|
+
? {
|
|
167
|
+
type: "file",
|
|
168
|
+
path: currentPath,
|
|
169
|
+
name: fileName,
|
|
170
|
+
getContent: async () => getFileContent(repoName, currentPath, apiClient, resolvedBranch),
|
|
171
|
+
}
|
|
172
|
+
: {
|
|
115
173
|
type: "directory",
|
|
116
|
-
path:
|
|
117
|
-
name:
|
|
174
|
+
path: currentPath,
|
|
175
|
+
name: fileName,
|
|
118
176
|
children: [],
|
|
119
177
|
};
|
|
178
|
+
nodeMap[currentPath] = currentNode;
|
|
179
|
+
if (pathParts.length === 1) {
|
|
180
|
+
root.push(currentNode);
|
|
120
181
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const pathParts = file.path.split("/");
|
|
126
|
-
const fileName = path_1.default.basename(file.path);
|
|
127
|
-
const isFile = file.type === "blob";
|
|
128
|
-
const currentPath = file.path;
|
|
129
|
-
const currentNode = isFile
|
|
130
|
-
? {
|
|
131
|
-
type: "file",
|
|
132
|
-
path: currentPath,
|
|
133
|
-
name: fileName,
|
|
134
|
-
getContent: async () => this.getFileContent(currentPath, branchName),
|
|
135
|
-
}
|
|
136
|
-
: {
|
|
182
|
+
else {
|
|
183
|
+
const parentPath = path_1.default.dirname(currentPath);
|
|
184
|
+
if (!nodeMap[parentPath]) {
|
|
185
|
+
const parentNode = {
|
|
137
186
|
type: "directory",
|
|
138
|
-
path:
|
|
139
|
-
name:
|
|
187
|
+
path: parentPath,
|
|
188
|
+
name: parentPath.split("/").pop() || "",
|
|
140
189
|
children: [],
|
|
141
190
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
else {
|
|
147
|
-
const parentPath = path_1.default.dirname(currentPath);
|
|
148
|
-
if (!nodeMap[parentPath]) {
|
|
149
|
-
const parentNode = {
|
|
150
|
-
type: "directory",
|
|
151
|
-
path: parentPath,
|
|
152
|
-
name: parentPath.split("/").pop() || "",
|
|
153
|
-
children: [],
|
|
154
|
-
};
|
|
155
|
-
nodeMap[parentPath] = parentNode;
|
|
156
|
-
const parentPathParts = parentPath.split("/");
|
|
157
|
-
if (parentPathParts.length === 1) {
|
|
158
|
-
root.push(parentNode);
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
const grandparentPath = path_1.default.dirname(parentPath);
|
|
162
|
-
if (nodeMap[grandparentPath] &&
|
|
163
|
-
nodeMap[grandparentPath].type === "directory") {
|
|
164
|
-
nodeMap[grandparentPath].children.push(parentNode);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
191
|
+
nodeMap[parentPath] = parentNode;
|
|
192
|
+
const parentPathParts = parentPath.split("/");
|
|
193
|
+
if (parentPathParts.length === 1) {
|
|
194
|
+
root.push(parentNode);
|
|
167
195
|
}
|
|
168
|
-
|
|
169
|
-
|
|
196
|
+
else {
|
|
197
|
+
const grandparentPath = path_1.default.dirname(parentPath);
|
|
198
|
+
if (nodeMap[grandparentPath] &&
|
|
199
|
+
nodeMap[grandparentPath].type === "directory") {
|
|
200
|
+
nodeMap[grandparentPath].children.push(parentNode);
|
|
201
|
+
}
|
|
170
202
|
}
|
|
171
203
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const fileReader = new GitHubFileReader(repoName, apiClient, REPO_OWNER);
|
|
184
|
-
return fileReader.getFileInfo(branchName);
|
|
204
|
+
if (nodeMap[parentPath].type === "directory") {
|
|
205
|
+
nodeMap[parentPath].children.push(currentNode);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
return {
|
|
210
|
+
type: "directory",
|
|
211
|
+
path: repoName,
|
|
212
|
+
name: repoName,
|
|
213
|
+
children: root,
|
|
214
|
+
};
|
|
185
215
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/create-pull-request/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AA6BvD,eAAO,MAAM,qBAAqB,EAAE,IAwDnC,CAAC"}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createPullRequestTool = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const utils_1 = require("../executor/utils");
|
|
6
|
+
const utils_2 = require("./utils");
|
|
7
|
+
const REPO_OWNER = "empirical-run";
|
|
5
8
|
const createPullRequestSchema = zod_1.z.object({
|
|
6
9
|
pullRequestTitle: zod_1.z
|
|
7
10
|
.string()
|
|
@@ -27,5 +30,31 @@ Don't ask the user for this information, just come up with it yourself.
|
|
|
27
30
|
parameters: createPullRequestSchema,
|
|
28
31
|
},
|
|
29
32
|
needsBrowser: false,
|
|
30
|
-
isInlineTool:
|
|
33
|
+
isInlineTool: true,
|
|
34
|
+
execute: async ({ input, apiClient, chatSession }) => {
|
|
35
|
+
const owner = REPO_OWNER;
|
|
36
|
+
try {
|
|
37
|
+
const valids = await (0, utils_2.validateInputs)({ input, apiClient, chatSession });
|
|
38
|
+
const { pullRequestTitle, pullRequestDescription, branchName } = valids;
|
|
39
|
+
const repo = await (0, utils_2.getRepoName)(chatSession, apiClient);
|
|
40
|
+
const existingPR = await (0, utils_1.getExistingPR)({
|
|
41
|
+
owner,
|
|
42
|
+
repo,
|
|
43
|
+
branchName,
|
|
44
|
+
apiClient: apiClient,
|
|
45
|
+
});
|
|
46
|
+
if (existingPR) {
|
|
47
|
+
return await (0, utils_2.handleExistingPullRequest)(existingPR, owner, repo, pullRequestDescription, chatSession, apiClient);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return await (0, utils_2.handleNewPullRequest)(owner, repo, pullRequestTitle, branchName, chatSession, pullRequestDescription, apiClient);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
isError: true,
|
|
56
|
+
result: `Failed to commit and push changes: ${error instanceof Error ? error.message : String(error)}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
},
|
|
31
60
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChatSessionInfo, IDashboardAPIClient } from "@empiricalrun/shared-types";
|
|
2
|
+
export interface ValidatedInputs {
|
|
3
|
+
pullRequestTitle: string;
|
|
4
|
+
pullRequestDescription: string;
|
|
5
|
+
branchName: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateInputs({ input, apiClient, chatSession, }: any): Promise<ValidatedInputs>;
|
|
8
|
+
export declare function getRepoName(chatSession: ChatSessionInfo | null | undefined, apiClient: IDashboardAPIClient): Promise<string>;
|
|
9
|
+
export declare function getMergeableStateInfo(owner: string, repo: string, pullRequest: any, apiClient: any): Promise<{
|
|
10
|
+
mergeableState: "unknown" | "clean" | "dirty" | "unstable";
|
|
11
|
+
stateDescription: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function handleExistingPullRequest(pullRequest: any, owner: string, repo: string, pullRequestDescription: string, chatSession: any, apiClient: any): Promise<{
|
|
14
|
+
isError: boolean;
|
|
15
|
+
result: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function handleNewPullRequest(owner: string, repo: string, pullRequestTitle: string, branchName: string, chatSession: any, pullRequestDescription: string, apiClient: any): Promise<{
|
|
18
|
+
isError: boolean;
|
|
19
|
+
result: string;
|
|
20
|
+
}>;
|
|
21
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/tools/create-pull-request/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAUpC,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,cAAc,CAAC,EACnC,KAAK,EACL,SAAS,EACT,WAAW,GACZ,EAAE,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,CAehC;AAED,wBAAsB,WAAW,CAC/B,WAAW,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAC/C,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,GAAG,EAChB,SAAS,EAAE,GAAG;;;GAUf;AAED,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,GAAG,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,sBAAsB,EAAE,MAAM,EAC9B,WAAW,EAAE,GAAG,EAChB,SAAS,EAAE,GAAG;;;GAqBf;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,EAChB,sBAAsB,EAAE,MAAM,EAC9B,SAAS,EAAE,GAAG;;;GAuBf"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateInputs = validateInputs;
|
|
4
|
+
exports.getRepoName = getRepoName;
|
|
5
|
+
exports.getMergeableStateInfo = getMergeableStateInfo;
|
|
6
|
+
exports.handleExistingPullRequest = handleExistingPullRequest;
|
|
7
|
+
exports.handleNewPullRequest = handleNewPullRequest;
|
|
8
|
+
const utils_1 = require("../executor/utils");
|
|
9
|
+
const pr_description_1 = require("../executor/utils/pr-description");
|
|
10
|
+
async function validateInputs({ input, apiClient, chatSession, }) {
|
|
11
|
+
const { pullRequestTitle, pullRequestDescription } = input;
|
|
12
|
+
const branchName = chatSession?.branchName;
|
|
13
|
+
if (!apiClient) {
|
|
14
|
+
throw new Error("Dashboard API client is not available.");
|
|
15
|
+
}
|
|
16
|
+
if (!branchName) {
|
|
17
|
+
throw new Error("Branch name is not available in the chat session.");
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
pullRequestTitle,
|
|
21
|
+
pullRequestDescription,
|
|
22
|
+
branchName,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function getRepoName(chatSession, apiClient) {
|
|
26
|
+
if (!chatSession?.id) {
|
|
27
|
+
throw new Error("Cannot create pull request without repo name or chat session ID.");
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const url = `/api/chat-sessions/${chatSession.id}/details`;
|
|
31
|
+
const sessionDetails = await apiClient.request(url, { method: "GET" });
|
|
32
|
+
if ("error" in sessionDetails) {
|
|
33
|
+
throw new Error(`Failed to fetch session details: ${sessionDetails.error}`);
|
|
34
|
+
}
|
|
35
|
+
if (!sessionDetails.gitPayload?.repoName) {
|
|
36
|
+
throw new Error("Repository name not found in session details.");
|
|
37
|
+
}
|
|
38
|
+
return sessionDetails.gitPayload.repoName;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw new Error(`Failed to fetch repository name: ${error instanceof Error ? error.message : String(error)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function getMergeableStateInfo(owner, repo, pullRequest, apiClient) {
|
|
45
|
+
const mergeableState = await (0, utils_1.getMergeableState)({
|
|
46
|
+
owner,
|
|
47
|
+
repo,
|
|
48
|
+
pullRequest,
|
|
49
|
+
apiClient,
|
|
50
|
+
});
|
|
51
|
+
const stateDescription = (0, utils_1.getMergeableStateDescription)(mergeableState);
|
|
52
|
+
return { mergeableState, stateDescription };
|
|
53
|
+
}
|
|
54
|
+
async function handleExistingPullRequest(pullRequest, owner, repo, pullRequestDescription, chatSession, apiClient) {
|
|
55
|
+
const updatedPR = await (0, utils_1.updatePullRequest)({
|
|
56
|
+
owner,
|
|
57
|
+
repo,
|
|
58
|
+
prNumber: pullRequest.number,
|
|
59
|
+
body: (0, pr_description_1.addMetadataToPRDescription)(pullRequestDescription, chatSession),
|
|
60
|
+
apiClient,
|
|
61
|
+
});
|
|
62
|
+
const { mergeableState, stateDescription } = await getMergeableStateInfo(owner, repo, updatedPR, apiClient);
|
|
63
|
+
return {
|
|
64
|
+
isError: false,
|
|
65
|
+
result: `Updated existing PR: ${updatedPR.html_url}\n\nMergeable state: ${mergeableState} - ${stateDescription}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async function handleNewPullRequest(owner, repo, pullRequestTitle, branchName, chatSession, pullRequestDescription, apiClient) {
|
|
69
|
+
const newPR = await (0, utils_1.createPullRequest)({
|
|
70
|
+
owner,
|
|
71
|
+
repo,
|
|
72
|
+
title: pullRequestTitle,
|
|
73
|
+
head: branchName,
|
|
74
|
+
base: chatSession?.baseBranchName || "main",
|
|
75
|
+
body: (0, pr_description_1.addMetadataToPRDescription)(pullRequestDescription, chatSession),
|
|
76
|
+
apiClient,
|
|
77
|
+
});
|
|
78
|
+
const { mergeableState, stateDescription } = await getMergeableStateInfo(owner, repo, newPR, apiClient);
|
|
79
|
+
return {
|
|
80
|
+
isError: false,
|
|
81
|
+
result: `Created a new PR: ${newPR.html_url}\n\nMergeable state: ${mergeableState} - ${stateDescription}`,
|
|
82
|
+
};
|
|
83
|
+
}
|