@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.
Files changed (155) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/agent/base/index.d.ts +43 -0
  3. package/dist/agent/base/index.d.ts.map +1 -0
  4. package/dist/agent/base/index.js +106 -0
  5. package/dist/agent/chat/agent-loop.d.ts +7 -7
  6. package/dist/agent/chat/agent-loop.d.ts.map +1 -1
  7. package/dist/agent/chat/agent-loop.js +5 -18
  8. package/dist/agent/chat/exports.d.ts +6 -4
  9. package/dist/agent/chat/exports.d.ts.map +1 -1
  10. package/dist/agent/chat/exports.js +9 -8
  11. package/dist/agent/chat/index.d.ts +6 -10
  12. package/dist/agent/chat/index.d.ts.map +1 -1
  13. package/dist/agent/chat/index.js +130 -200
  14. package/dist/agent/chat/prompt/index.d.ts +5 -4
  15. package/dist/agent/chat/prompt/index.d.ts.map +1 -1
  16. package/dist/agent/chat/prompt/index.js +79 -68
  17. package/dist/agent/chat/state.d.ts +3 -5
  18. package/dist/agent/chat/state.d.ts.map +1 -1
  19. package/dist/agent/chat/state.js +2 -10
  20. package/dist/agent/chat/utils.d.ts +2 -4
  21. package/dist/agent/chat/utils.d.ts.map +1 -1
  22. package/dist/agent/chat/utils.js +2 -16
  23. package/dist/agent/cli.d.ts +11 -0
  24. package/dist/agent/cli.d.ts.map +1 -0
  25. package/dist/agent/cli.js +209 -0
  26. package/dist/agent/code-review/index.d.ts +7 -0
  27. package/dist/agent/code-review/index.d.ts.map +1 -0
  28. package/dist/agent/code-review/index.js +65 -0
  29. package/dist/agent/code-review/prompt.d.ts +1 -1
  30. package/dist/agent/code-review/prompt.d.ts.map +1 -1
  31. package/dist/agent/code-review/prompt.js +52 -16
  32. package/dist/agent/index.d.ts +10 -0
  33. package/dist/agent/index.d.ts.map +1 -0
  34. package/dist/agent/index.js +19 -0
  35. package/dist/agent/triage/index.d.ts +7 -0
  36. package/dist/agent/triage/index.d.ts.map +1 -0
  37. package/dist/agent/triage/index.js +102 -0
  38. package/dist/agent/video-analysis/index.d.ts +7 -0
  39. package/dist/agent/video-analysis/index.d.ts.map +1 -0
  40. package/dist/agent/video-analysis/index.js +35 -0
  41. package/dist/bin/index.js +6 -6
  42. package/dist/file-info/adapters/github/index.d.ts +2 -2
  43. package/dist/file-info/adapters/github/index.d.ts.map +1 -1
  44. package/dist/file-info/adapters/github/index.js +4 -4
  45. package/dist/file-info/adapters/github/reader.d.ts +5 -10
  46. package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
  47. package/dist/file-info/adapters/github/reader.js +168 -138
  48. package/dist/tools/create-pull-request/index.d.ts.map +1 -0
  49. package/dist/tools/{definitions/commit-and-create-pr.js → create-pull-request/index.js} +30 -1
  50. package/dist/tools/create-pull-request/utils.d.ts +21 -0
  51. package/dist/tools/create-pull-request/utils.d.ts.map +1 -0
  52. package/dist/tools/create-pull-request/utils.js +83 -0
  53. package/dist/tools/definitions/extract-frames-from-video.d.ts +39 -0
  54. package/dist/tools/definitions/extract-frames-from-video.d.ts.map +1 -0
  55. package/dist/tools/definitions/extract-frames-from-video.js +60 -0
  56. package/dist/tools/definitions/fetch-video-analysis.d.ts +28 -0
  57. package/dist/tools/definitions/fetch-video-analysis.d.ts.map +1 -1
  58. package/dist/tools/definitions/fetch-video-analysis.js +39 -4
  59. package/dist/tools/definitions/rename-file.d.ts +3 -0
  60. package/dist/tools/definitions/rename-file.d.ts.map +1 -0
  61. package/dist/tools/definitions/rename-file.js +23 -0
  62. package/dist/tools/delete-file/index.d.ts.map +1 -1
  63. package/dist/tools/delete-file/index.js +13 -1
  64. package/dist/tools/executor/index.d.ts +1 -1
  65. package/dist/tools/executor/index.d.ts.map +1 -1
  66. package/dist/tools/executor/index.js +22 -7
  67. package/dist/tools/executor/utils/checkpoint.d.ts +1 -3
  68. package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -1
  69. package/dist/tools/executor/utils/checkpoint.js +17 -17
  70. package/dist/tools/executor/utils/git.d.ts +9 -1
  71. package/dist/tools/executor/utils/git.d.ts.map +1 -1
  72. package/dist/tools/executor/utils/git.js +72 -2
  73. package/dist/tools/extract-frames-from-video/index.d.ts +7 -0
  74. package/dist/tools/extract-frames-from-video/index.d.ts.map +1 -0
  75. package/dist/tools/extract-frames-from-video/index.js +145 -0
  76. package/dist/tools/{fetch-image → fetch-file}/index.d.ts +2 -2
  77. package/dist/tools/fetch-file/index.d.ts.map +1 -0
  78. package/dist/tools/fetch-file/index.js +97 -0
  79. package/dist/tools/fetch-session-diff/index.d.ts +3 -0
  80. package/dist/tools/fetch-session-diff/index.d.ts.map +1 -0
  81. package/dist/tools/fetch-session-diff/index.js +46 -0
  82. package/dist/tools/fetch-video-analysis/index.d.ts +3 -3
  83. package/dist/tools/fetch-video-analysis/index.d.ts.map +1 -1
  84. package/dist/tools/fetch-video-analysis/index.js +84 -24
  85. package/dist/tools/fetch-video-analysis/open-ai.d.ts +6 -0
  86. package/dist/tools/fetch-video-analysis/open-ai.d.ts.map +1 -0
  87. package/dist/tools/fetch-video-analysis/open-ai.js +37 -0
  88. package/dist/tools/fetch-video-analysis/utils.d.ts +9 -3
  89. package/dist/tools/fetch-video-analysis/utils.d.ts.map +1 -1
  90. package/dist/tools/fetch-video-analysis/utils.js +64 -15
  91. package/dist/tools/fetch-video-analysis/video-analysis.d.ts +2 -2
  92. package/dist/tools/fetch-video-analysis/video-analysis.d.ts.map +1 -1
  93. package/dist/tools/fetch-video-analysis/video-analysis.js +24 -8
  94. package/dist/tools/file-operations/create.d.ts.map +1 -1
  95. package/dist/tools/file-operations/create.js +6 -3
  96. package/dist/tools/file-operations/insert.d.ts.map +1 -1
  97. package/dist/tools/file-operations/insert.js +6 -3
  98. package/dist/tools/file-operations/replace.d.ts.map +1 -1
  99. package/dist/tools/file-operations/replace.js +6 -3
  100. package/dist/tools/file-operations/shared/git-helper.d.ts.map +1 -1
  101. package/dist/tools/file-operations/shared/git-helper.js +1 -1
  102. package/dist/tools/file-operations/view/index.d.ts +2 -5
  103. package/dist/tools/file-operations/view/index.d.ts.map +1 -1
  104. package/dist/tools/file-operations/view/index.js +2 -22
  105. package/dist/tools/index.d.ts +28 -2
  106. package/dist/tools/index.d.ts.map +1 -1
  107. package/dist/tools/index.js +50 -22
  108. package/dist/tools/issues/update-issue.d.ts.map +1 -1
  109. package/dist/tools/issues/update-issue.js +16 -9
  110. package/dist/tools/merge-conflicts/index.js +1 -1
  111. package/dist/tools/rename-file/index.d.ts +3 -0
  112. package/dist/tools/rename-file/index.d.ts.map +1 -0
  113. package/dist/tools/rename-file/index.js +88 -0
  114. package/dist/tools/review-pull-request/index.d.ts +3 -0
  115. package/dist/tools/review-pull-request/index.d.ts.map +1 -0
  116. package/dist/tools/review-pull-request/index.js +103 -0
  117. package/dist/tools/run-test.js +2 -2
  118. package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
  119. package/dist/tools/test-run-fetcher/index.js +4 -14
  120. package/dist/tools/trace-dot-zip/index.d.ts.map +1 -1
  121. package/dist/tools/trace-dot-zip/index.js +2 -1
  122. package/dist/tools/trace-dot-zip/types.d.ts +35 -3
  123. package/dist/tools/trace-dot-zip/types.d.ts.map +1 -1
  124. package/dist/tools/trace-dot-zip/utils/network-trace.d.ts +7 -2
  125. package/dist/tools/trace-dot-zip/utils/network-trace.d.ts.map +1 -1
  126. package/dist/tools/trace-dot-zip/utils/network-trace.js +130 -10
  127. package/dist/tools/upgrade-packages/index.js +1 -1
  128. package/dist/tools/utils/urls.d.ts +5 -0
  129. package/dist/tools/utils/urls.d.ts.map +1 -0
  130. package/dist/tools/utils/urls.js +19 -0
  131. package/dist/tools/view-failed-test-run-report/index.d.ts.map +1 -1
  132. package/dist/tools/view-failed-test-run-report/index.js +3 -15
  133. package/dist/utils/file.d.ts +1 -0
  134. package/dist/utils/file.d.ts.map +1 -1
  135. package/dist/utils/file.js +45 -1
  136. package/dist/utils/index.d.ts +0 -1
  137. package/dist/utils/index.d.ts.map +1 -1
  138. package/dist/utils/index.js +1 -3
  139. package/dist/utils/local-ffmpeg-client.d.ts +27 -0
  140. package/dist/utils/local-ffmpeg-client.d.ts.map +1 -0
  141. package/dist/{tools/fetch-video-analysis → utils}/local-ffmpeg-client.js +117 -27
  142. package/package.json +5 -5
  143. package/tsconfig.tsbuildinfo +1 -1
  144. package/dist/agent/chat/utils/tool-calls.d.ts +0 -21
  145. package/dist/agent/chat/utils/tool-calls.d.ts.map +0 -1
  146. package/dist/agent/chat/utils/tool-calls.js +0 -64
  147. package/dist/tools/commit-and-create-pr/index.d.ts.map +0 -1
  148. package/dist/tools/commit-and-create-pr/index.js +0 -83
  149. package/dist/tools/definitions/commit-and-create-pr.d.ts +0 -3
  150. package/dist/tools/definitions/commit-and-create-pr.d.ts.map +0 -1
  151. package/dist/tools/fetch-image/index.d.ts.map +0 -1
  152. package/dist/tools/fetch-image/index.js +0 -63
  153. package/dist/tools/fetch-video-analysis/local-ffmpeg-client.d.ts +0 -24
  154. package/dist/tools/fetch-video-analysis/local-ffmpeg-client.d.ts.map +0 -1
  155. /package/dist/tools/{commit-and-create-pr → create-pull-request}/index.d.ts +0 -0
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.truncateJsonValues = exports.getTypescriptTestBlock = void 0;
3
+ exports.getTypescriptTestBlock = void 0;
4
4
  var web_1 = require("../bin/utils/platform/web");
5
5
  Object.defineProperty(exports, "getTypescriptTestBlock", { enumerable: true, get: function () { return web_1.getTypescriptTestBlock; } });
6
- var json_1 = require("./json");
7
- Object.defineProperty(exports, "truncateJsonValues", { enumerable: true, get: function () { return json_1.truncateJsonValues; } });
@@ -0,0 +1,27 @@
1
+ import { UniqueFrameWithMetadata } from "@empiricalrun/shared-types";
2
+ export declare class LocalFFmpegClient {
3
+ private static readonly MAX_VIDEO_DURATION_SECONDS;
4
+ private static readonly CHUNK_DURATION_SECONDS;
5
+ constructor();
6
+ private checkFFmpegAvailability;
7
+ private getVideoDuration;
8
+ private validateVideoChunk;
9
+ private downloadVideo;
10
+ private ensureEmptyDir;
11
+ private runFFmpegCommand;
12
+ private createVideoChunks;
13
+ private extractFramesToFiles;
14
+ private processVideoChunks;
15
+ storeUniqueFrames(uniqueFrames: UniqueFrameWithMetadata[], workingDir: string): Promise<string>;
16
+ extractVideoFrames(videoUrl: string, outputDir: string, options?: {
17
+ fps?: number;
18
+ threshold?: number;
19
+ startTime?: number;
20
+ duration?: number;
21
+ }): Promise<{
22
+ totalFramesCount: number;
23
+ uniqueFrames: UniqueFrameWithMetadata[];
24
+ videoDurationSeconds: number;
25
+ }>;
26
+ }
27
+ //# sourceMappingURL=local-ffmpeg-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-ffmpeg-client.d.ts","sourceRoot":"","sources":["../../src/utils/local-ffmpeg-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAUrE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAW;IAC7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAU;;IAMxD,OAAO,CAAC,uBAAuB;YAWjB,gBAAgB;YAiBhB,kBAAkB;YAgClB,aAAa;YAeb,cAAc;YASd,gBAAgB;YAoBhB,iBAAiB;YAsEjB,oBAAoB;YAyCpB,kBAAkB;IA2D1B,iBAAiB,CACrB,YAAY,EAAE,uBAAuB,EAAE,EACvC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;IAiCZ,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GACA,OAAO,CAAC;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,uBAAuB,EAAE,CAAC;QACxC,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;CA2GH"}
@@ -8,7 +8,7 @@ const child_process_1 = require("child_process");
8
8
  const fs_1 = require("fs");
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const util_1 = require("util");
11
- const dedup_image_fs_1 = require("../../utils/dedup-image-fs");
11
+ const dedup_image_fs_1 = require("./dedup-image-fs");
12
12
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
13
13
  class LocalFFmpegClient {
14
14
  static MAX_VIDEO_DURATION_SECONDS = 15 * 60; // 15 minutes
@@ -75,18 +75,56 @@ class LocalFFmpegClient {
75
75
  const buffer = await response.arrayBuffer();
76
76
  await fs_1.promises.writeFile(outputPath, Buffer.from(buffer));
77
77
  }
78
- async createVideoChunks(videoPath, outputDir, duration) {
78
+ async ensureEmptyDir(dir) {
79
+ try {
80
+ await fs_1.promises.rm(dir, { recursive: true, force: true });
81
+ }
82
+ catch {
83
+ // ignore
84
+ }
85
+ await fs_1.promises.mkdir(dir, { recursive: true });
86
+ }
87
+ async runFFmpegCommand({ inputPath, args, outputPath, }) {
88
+ const quotedInput = `"${inputPath}"`;
89
+ const output = outputPath ? ` "${outputPath}"` : "";
90
+ const cmd = `ffmpeg -y -nostdin -i ${quotedInput} ${args.join(" ")}${output}`;
91
+ try {
92
+ await execAsync(cmd);
93
+ }
94
+ catch (error) {
95
+ throw new Error(`ffmpeg command failed: ${cmd} => ${String(error)}`);
96
+ }
97
+ }
98
+ async createVideoChunks(videoPath, outputDir, duration, startTime = 0) {
79
99
  const chunkPaths = [];
80
100
  const chunkCount = Math.ceil(duration / LocalFFmpegClient.CHUNK_DURATION_SECONDS);
81
101
  console.log(`Creating ${chunkCount} chunks of ${LocalFFmpegClient.CHUNK_DURATION_SECONDS} seconds each`);
82
102
  for (let i = 0; i < chunkCount; i++) {
83
- const startTime = i * LocalFFmpegClient.CHUNK_DURATION_SECONDS;
103
+ const chunkOffsetTime = i * LocalFFmpegClient.CHUNK_DURATION_SECONDS;
104
+ const absoluteStartTime = startTime + chunkOffsetTime;
84
105
  const chunkPath = path_1.default.join(outputDir, `chunk_${i.toString().padStart(3, "0")}.mp4`);
85
- const remainingDuration = duration - startTime;
106
+ const remainingDuration = duration - chunkOffsetTime;
86
107
  const chunkDuration = Math.min(LocalFFmpegClient.CHUNK_DURATION_SECONDS, remainingDuration);
87
- const command = `ffmpeg -i "${videoPath}" -ss ${startTime} -t ${chunkDuration} -c:v libx264 -c:a aac -preset ultrafast -crf 28 "${chunkPath}"`;
88
108
  try {
89
- await execAsync(command);
109
+ await fs_1.promises.rm(chunkPath, { force: true });
110
+ await this.runFFmpegCommand({
111
+ inputPath: videoPath,
112
+ args: [
113
+ "-ss",
114
+ String(absoluteStartTime),
115
+ "-t",
116
+ String(chunkDuration),
117
+ "-c:v",
118
+ "libx264",
119
+ "-c:a",
120
+ "aac",
121
+ "-preset",
122
+ "ultrafast",
123
+ "-crf",
124
+ "28",
125
+ ],
126
+ outputPath: chunkPath,
127
+ });
90
128
  // Validate the created chunk
91
129
  const isValid = await this.validateVideoChunk(chunkPath);
92
130
  if (isValid) {
@@ -108,14 +146,17 @@ class LocalFFmpegClient {
108
146
  }
109
147
  return chunkPaths;
110
148
  }
111
- async extractFramesToFiles(videoPath, outputDir, chunkIndex) {
112
- await fs_1.promises.mkdir(outputDir, { recursive: true });
149
+ async extractFramesToFiles(videoPath, outputDir, chunkIndex, fps) {
150
+ await this.ensureEmptyDir(outputDir);
113
151
  const framePrefix = chunkIndex !== undefined ? `chunk${chunkIndex}_frame` : "frame";
114
152
  const framePattern = path_1.default.join(outputDir, `${framePrefix}_%04d.png`);
115
- const command = `ffmpeg -i "${videoPath}" -vf "fps=30" "${framePattern}"`;
116
- console.log(`Extracting frames with command: ${command}`);
153
+ console.log(`Extracting frames with command: ffmpeg -i "${videoPath}" -vf "fps=${fps}" "${framePattern}"`);
117
154
  try {
118
- await execAsync(command);
155
+ await this.runFFmpegCommand({
156
+ inputPath: videoPath,
157
+ args: ["-vf", `fps=${fps}`],
158
+ outputPath: framePattern,
159
+ });
119
160
  }
120
161
  catch (error) {
121
162
  throw new Error(`Frame extraction failed: ${error}`);
@@ -128,10 +169,10 @@ class LocalFFmpegClient {
128
169
  console.log(`Extracted ${frameFiles.length} frames from ${chunkIndex !== undefined ? `chunk ${chunkIndex}` : "video"}`);
129
170
  return frameFiles;
130
171
  }
131
- async processVideoChunks(chunkPaths, workingDir) {
172
+ async processVideoChunks(chunkPaths, workingDir, fps) {
132
173
  const allFramePaths = [];
133
174
  const consolidatedFramesDir = path_1.default.join(workingDir, "consolidated_frames");
134
- await fs_1.promises.mkdir(consolidatedFramesDir, { recursive: true });
175
+ await this.ensureEmptyDir(consolidatedFramesDir);
135
176
  let globalFrameIndex = 0;
136
177
  for (let i = 0; i < chunkPaths.length; i++) {
137
178
  const chunkPath = chunkPaths[i];
@@ -141,7 +182,7 @@ class LocalFFmpegClient {
141
182
  throw new Error(`Chunk path is undefined for chunk ${i + 1}`);
142
183
  }
143
184
  try {
144
- const chunkFramePaths = await this.extractFramesToFiles(chunkPath, chunkFramesDir, i);
185
+ const chunkFramePaths = await this.extractFramesToFiles(chunkPath, chunkFramesDir, i, fps);
145
186
  for (const framePath of chunkFramePaths) {
146
187
  const newFramePath = path_1.default.join(consolidatedFramesDir, `frame_${globalFrameIndex.toString().padStart(6, "0")}.png`);
147
188
  await fs_1.promises.rename(framePath, newFramePath);
@@ -165,24 +206,75 @@ class LocalFFmpegClient {
165
206
  }
166
207
  return allFramePaths;
167
208
  }
168
- async extractVideoFrames(videoUrl, outputDir) {
209
+ async storeUniqueFrames(uniqueFrames, workingDir) {
210
+ const uniqueFramesDir = path_1.default.join(workingDir, "unique_frames");
211
+ await this.ensureEmptyDir(uniqueFramesDir);
212
+ console.log(`Storing ${uniqueFrames.length} unique frames in ${uniqueFramesDir}`);
213
+ for (let i = 0; i < uniqueFrames.length; i++) {
214
+ const frame = uniqueFrames[i];
215
+ if (!frame)
216
+ continue;
217
+ const originalPath = frame.metadata.path;
218
+ const uniqueFramePath = path_1.default.join(uniqueFramesDir, `unique_frame_${i.toString().padStart(4, "0")}.png`);
219
+ try {
220
+ await fs_1.promises.copyFile(originalPath, uniqueFramePath);
221
+ }
222
+ catch (error) {
223
+ console.warn(`Failed to copy frame ${originalPath} to ${uniqueFramePath}:`, error);
224
+ }
225
+ }
226
+ console.log(`Stored ${uniqueFrames.length} unique frames in: ${uniqueFramesDir}`);
227
+ return uniqueFramesDir;
228
+ }
229
+ async extractVideoFrames(videoUrl, outputDir, options) {
169
230
  const workingDir = path_1.default.join(process.cwd(), outputDir);
170
- const videoPath = path_1.default.join(workingDir, `video-${Date.now()}.webm`);
231
+ const videoPath = path_1.default.join(workingDir, `video_${Date.now()}.webm`);
232
+ const fps = options?.fps ?? 30;
233
+ const threshold = options?.threshold ?? 0.001;
234
+ const startTime = options?.startTime;
235
+ const duration = options?.duration;
171
236
  try {
172
237
  await fs_1.promises.mkdir(workingDir, { recursive: true });
173
238
  await this.downloadVideo(videoUrl, videoPath);
174
- const duration = await this.getVideoDuration(videoPath);
175
- console.log(`Video duration: ${Math.round(duration)} seconds`);
176
- if (duration > LocalFFmpegClient.MAX_VIDEO_DURATION_SECONDS) {
177
- throw new Error(`Video duration (${Math.round(duration)}s) exceeds maximum allowed duration (${LocalFFmpegClient.MAX_VIDEO_DURATION_SECONDS}s)`);
239
+ const videoDuration = await this.getVideoDuration(videoPath);
240
+ console.log(`Video duration: ${Math.round(videoDuration)} seconds`);
241
+ if (videoDuration > LocalFFmpegClient.MAX_VIDEO_DURATION_SECONDS) {
242
+ throw new Error(`Video duration (${Math.round(videoDuration)}s) exceeds maximum allowed duration (${LocalFFmpegClient.MAX_VIDEO_DURATION_SECONDS}s)`);
243
+ }
244
+ // Validate and adjust time parameters
245
+ let effectiveStartTime = 0;
246
+ let effectiveDuration = videoDuration;
247
+ if (startTime !== undefined) {
248
+ if (startTime < 0) {
249
+ throw new Error(`Start time cannot be negative: ${startTime}`);
250
+ }
251
+ if (startTime >= videoDuration) {
252
+ throw new Error(`Start time (${startTime}s) exceeds video duration (${Math.round(videoDuration)}s)`);
253
+ }
254
+ effectiveStartTime = startTime;
255
+ effectiveDuration = videoDuration - startTime;
178
256
  }
179
- const chunkPaths = await this.createVideoChunks(videoPath, workingDir, duration);
180
- const allFramePaths = await this.processVideoChunks(chunkPaths, workingDir);
257
+ if (duration !== undefined) {
258
+ if (duration <= 0) {
259
+ throw new Error(`Duration must be positive: ${duration}`);
260
+ }
261
+ const maxAllowedDuration = videoDuration - effectiveStartTime;
262
+ if (duration > maxAllowedDuration) {
263
+ console.warn(`Requested duration (${duration}s) exceeds available time (${maxAllowedDuration}s), truncating to fit`);
264
+ effectiveDuration = maxAllowedDuration;
265
+ }
266
+ else {
267
+ effectiveDuration = duration;
268
+ }
269
+ }
270
+ console.log(`Effective extraction range: ${effectiveStartTime}s to ${effectiveStartTime + effectiveDuration}s`);
271
+ const chunkPaths = await this.createVideoChunks(videoPath, workingDir, effectiveDuration, effectiveStartTime);
272
+ const allFramePaths = await this.processVideoChunks(chunkPaths, workingDir, fps);
181
273
  const allFramesCount = allFramePaths.length;
182
274
  const uniqueImages = await (0, dedup_image_fs_1.deduplicateImageFiles)({
183
275
  imagePaths: allFramePaths,
184
276
  batchSize: 50,
185
- threshold: 0.001,
277
+ threshold,
186
278
  logPrefix: "ffmpeg-chunk-frame-dedup",
187
279
  });
188
280
  console.log(`Filtered to ${uniqueImages.length} unique frames from ${allFramesCount} total frames across ${chunkPaths.length} chunks`);
@@ -192,18 +284,16 @@ class LocalFFmpegClient {
192
284
  }
193
285
  throw new Error("No frames were extracted from the video");
194
286
  }
287
+ await this.storeUniqueFrames(uniqueImages, workingDir);
195
288
  return {
196
289
  totalFramesCount: allFramesCount,
197
- uniqueFramesCount: uniqueImages.length,
198
290
  uniqueFrames: uniqueImages,
291
+ videoDurationSeconds: videoDuration,
199
292
  };
200
293
  }
201
294
  catch (error) {
202
295
  throw new Error(`Frame extraction failed: ${error instanceof Error ? error.message : String(error)}`);
203
296
  }
204
- finally {
205
- await fs_1.promises.rm(workingDir, { recursive: true });
206
- }
207
297
  }
208
298
  }
209
299
  exports.LocalFFmpegClient = LocalFFmpegClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.74.2",
3
+ "version": "0.76.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -85,9 +85,9 @@
85
85
  "yauzl": "^3.1.3",
86
86
  "zod": "^3.23.8",
87
87
  "@empiricalrun/ast-parser": "^0.0.10",
88
- "@empiricalrun/llm": "^0.21.0",
89
- "@empiricalrun/r2-uploader": "^0.3.10",
90
- "@empiricalrun/test-run": "^0.11.0"
88
+ "@empiricalrun/llm": "^0.22.0",
89
+ "@empiricalrun/r2-uploader": "^0.3.11",
90
+ "@empiricalrun/test-run": "^0.11.1"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@playwright/test": "1.53.2",
@@ -106,7 +106,7 @@
106
106
  "playwright": "1.53.2",
107
107
  "serve-handler": "^6.1.6",
108
108
  "ts-patch": "^3.3.0",
109
- "@empiricalrun/shared-types": "0.10.0"
109
+ "@empiricalrun/shared-types": "0.11.0"
110
110
  },
111
111
  "scripts": {
112
112
  "dev": "tspc --build --watch",
@@ -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/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/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/filesystem-cache.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/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/chat/utils/tool-calls.ts","./src/agent/code-review/prompt.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/for-recorder.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/cua/pw-codegen/pw-pause/types.ts","./src/agent/cua/pw-codegen/pw-pause/utils.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-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/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.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/environments.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/totp.ts","./src/dashboard/types.ts","./src/errors/index.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.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/index.ts","./src/file-info/adapters/github/reader.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/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/commit-and-create-pr/index.ts","./src/tools/definitions/commit-and-create-pr.ts","./src/tools/definitions/delete-file.ts","./src/tools/definitions/download-build.ts","./src/tools/definitions/fetch-video-analysis.ts","./src/tools/definitions/grep.ts","./src/tools/definitions/list-tests-and-projects.ts","./src/tools/definitions/merge-conflicts.ts","./src/tools/definitions/run-test.ts","./src/tools/definitions/str_replace_editor.ts","./src/tools/definitions/test-gen-browser.ts","./src/tools/definitions/upgrade-packages.ts","./src/tools/definitions/utils.ts","./src/tools/delete-file/index.ts","./src/tools/download-build/index.ts","./src/tools/executor/index.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-image/index.ts","./src/tools/fetch-last-successful-test-run/index.ts","./src/tools/fetch-video-analysis/index.ts","./src/tools/fetch-video-analysis/local-ffmpeg-client.ts","./src/tools/fetch-video-analysis/utils.ts","./src/tools/fetch-video-analysis/video-analysis.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/git-helper.ts","./src/tools/file-operations/shared/helpers.ts","./src/tools/file-operations/view/index.ts","./src/tools/grep/index.ts","./src/tools/grep/types.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/issues/create-issue.ts","./src/tools/issues/index.ts","./src/tools/issues/list-issues.ts","./src/tools/issues/metadata-schema.ts","./src/tools/issues/update-issue.ts","./src/tools/issues/utils.ts","./src/tools/list-tests-and-projects/index.ts","./src/tools/merge-conflicts/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-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/upgrade-packages/index.ts","./src/tools/upgrade-packages/utils.ts","./src/tools/utils/queue.ts","./src/tools/view-failed-test-run-report/index.ts","./src/trace-utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/utils/SQSClient.ts","./src/utils/dedup-image-fs.ts","./src/utils/dedup-image.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/model.ts","./src/utils/playwright-report-parser.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}
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/skill.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/filesystem-cache.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/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/code-review/index.ts","./src/agent/code-review/prompt.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/for-recorder.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/cua/pw-codegen/pw-pause/types.ts","./src/agent/cua/pw-codegen/pw-pause/utils.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-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/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/agent/triage/index.ts","./src/agent/video-analysis/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/environments.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/totp.ts","./src/dashboard/types.ts","./src/errors/index.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.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/index.ts","./src/file-info/adapters/github/reader.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/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/create-pull-request/index.ts","./src/tools/create-pull-request/utils.ts","./src/tools/definitions/delete-file.ts","./src/tools/definitions/download-build.ts","./src/tools/definitions/extract-frames-from-video.ts","./src/tools/definitions/fetch-video-analysis.ts","./src/tools/definitions/grep.ts","./src/tools/definitions/list-tests-and-projects.ts","./src/tools/definitions/merge-conflicts.ts","./src/tools/definitions/rename-file.ts","./src/tools/definitions/run-test.ts","./src/tools/definitions/str_replace_editor.ts","./src/tools/definitions/test-gen-browser.ts","./src/tools/definitions/upgrade-packages.ts","./src/tools/definitions/utils.ts","./src/tools/delete-file/index.ts","./src/tools/download-build/index.ts","./src/tools/executor/index.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/extract-frames-from-video/index.ts","./src/tools/fetch-file/index.ts","./src/tools/fetch-last-successful-test-run/index.ts","./src/tools/fetch-session-diff/index.ts","./src/tools/fetch-video-analysis/index.ts","./src/tools/fetch-video-analysis/open-ai.ts","./src/tools/fetch-video-analysis/utils.ts","./src/tools/fetch-video-analysis/video-analysis.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/git-helper.ts","./src/tools/file-operations/shared/helpers.ts","./src/tools/file-operations/view/index.ts","./src/tools/grep/index.ts","./src/tools/grep/types.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/issues/create-issue.ts","./src/tools/issues/index.ts","./src/tools/issues/list-issues.ts","./src/tools/issues/metadata-schema.ts","./src/tools/issues/update-issue.ts","./src/tools/issues/utils.ts","./src/tools/list-tests-and-projects/index.ts","./src/tools/merge-conflicts/index.ts","./src/tools/rename-file/index.ts","./src/tools/review-pull-request/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-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/upgrade-packages/index.ts","./src/tools/upgrade-packages/utils.ts","./src/tools/utils/queue.ts","./src/tools/utils/urls.ts","./src/tools/view-failed-test-run-report/index.ts","./src/trace-utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/utils/SQSClient.ts","./src/utils/dedup-image-fs.ts","./src/utils/dedup-image.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/local-ffmpeg-client.ts","./src/utils/model.ts","./src/utils/playwright-report-parser.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}
@@ -1,21 +0,0 @@
1
- import { IChatModel } from "@empiricalrun/llm/chat";
2
- import type { ChatState, PendingToolCall, SupportedChatModels, ToolResult } from "@empiricalrun/shared-types";
3
- export declare function rejectPendingToolCalls({ chatState, chatModel, }: {
4
- chatState: ChatState;
5
- chatModel: IChatModel<any>;
6
- }): ChatState;
7
- export declare function filterPendingToolCalls({ toolCalls, toolResults, pendingToolCalls, }: {
8
- toolCalls: PendingToolCall[];
9
- toolResults: ToolResult[];
10
- pendingToolCalls: PendingToolCall[];
11
- }): {
12
- filteredToolCalls: PendingToolCall[];
13
- filteredToolResults: ToolResult[];
14
- };
15
- export declare function processToolCallsAndUpdateChatState({ toolCalls, toolResults, chatModel, selectedModel, }: {
16
- toolCalls: PendingToolCall[];
17
- toolResults: ToolResult[];
18
- chatModel: IChatModel<any>;
19
- selectedModel: SupportedChatModels;
20
- }): ChatState | undefined;
21
- //# sourceMappingURL=tool-calls.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-calls.d.ts","sourceRoot":"","sources":["../../../../src/agent/chat/utils/tool-calls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,UAAU,EACX,MAAM,4BAA4B,CAAC;AAOpC,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,SAAS,GACV,EAAE;IACD,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;CAC5B,GAAG,SAAS,CA8BZ;AAED,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,EAAE;IACD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,gBAAgB,EAAE,eAAe,EAAE,CAAC;CACrC;;;EAgBA;AAED,wBAAgB,kCAAkC,CAAC,EACjD,SAAS,EACT,WAAW,EACX,SAAS,EACT,aAAa,GACd,EAAE;IACD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC;CACpC,GAAG,SAAS,GAAG,SAAS,CAkBxB"}
@@ -1,64 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.rejectPendingToolCalls = rejectPendingToolCalls;
4
- exports.filterPendingToolCalls = filterPendingToolCalls;
5
- exports.processToolCallsAndUpdateChatState = processToolCallsAndUpdateChatState;
6
- const state_1 = require("../state");
7
- const TOOL_CALL_REJECTED_BY_USER_ERROR = "This tool call was rejected by the user.";
8
- function rejectPendingToolCalls({ chatState, chatModel, }) {
9
- const pendingToolCalls = chatModel.getPendingToolCalls();
10
- let updatedChatState = {
11
- ...chatState,
12
- // When tool calls are rejected, we reset askUserForInput to true
13
- // so that the user can provide input for the next tool call. The agent
14
- // loop is not run again until the user provides input.
15
- askUserForInput: true,
16
- };
17
- if (pendingToolCalls.length > 0) {
18
- const toolResults = pendingToolCalls.map((toolCall) => {
19
- console.log(`Rejecting pending tool calls with toolCallId: ${toolCall.id} `);
20
- return {
21
- isError: true,
22
- result: TOOL_CALL_REJECTED_BY_USER_ERROR,
23
- };
24
- });
25
- chatModel.pushToolResultsMessage(pendingToolCalls, toolResults);
26
- return {
27
- ...updatedChatState,
28
- messages: chatModel.messages,
29
- };
30
- }
31
- return updatedChatState;
32
- }
33
- function filterPendingToolCalls({ toolCalls, toolResults, pendingToolCalls, }) {
34
- const filteredToolResults = [];
35
- const filteredToolCalls = toolCalls.filter((call, index) => {
36
- if (pendingToolCalls.some((p) => p.id === call.id)) {
37
- filteredToolResults.push(toolResults[index]);
38
- return true;
39
- }
40
- return false;
41
- });
42
- return {
43
- filteredToolCalls,
44
- filteredToolResults,
45
- };
46
- }
47
- function processToolCallsAndUpdateChatState({ toolCalls, toolResults, chatModel, selectedModel, }) {
48
- const pendingToolCalls = chatModel.getPendingToolCalls() || [];
49
- const { filteredToolCalls, filteredToolResults } = filterPendingToolCalls({
50
- toolCalls,
51
- toolResults,
52
- pendingToolCalls,
53
- });
54
- if (filteredToolCalls.length > 0) {
55
- chatModel.pushToolResultsMessage(filteredToolCalls, filteredToolResults);
56
- const newChatState = (0, state_1.createChatStateForMessages)({
57
- messages: chatModel.messages || [],
58
- selectedModel,
59
- askUserForInput: chatModel.askUserForInput,
60
- error: null,
61
- });
62
- return newChatState;
63
- }
64
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/commit-and-create-pr/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAevD,eAAO,MAAM,qBAAqB,EAAE,IAgFnC,CAAC"}
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createPullRequestTool = void 0;
4
- const child_process_1 = require("child_process");
5
- const commit_and_create_pr_1 = require("../definitions/commit-and-create-pr");
6
- const utils_1 = require("../executor/utils");
7
- const git_1 = require("../executor/utils/git");
8
- const pr_description_1 = require("../executor/utils/pr-description");
9
- exports.createPullRequestTool = {
10
- ...commit_and_create_pr_1.createPullRequestTool,
11
- execute: async ({ input, repoPath, apiClient, chatSession }) => {
12
- try {
13
- const { pullRequestTitle, pullRequestDescription } = input;
14
- const remoteUrl = (0, child_process_1.execSync)("git config --get remote.origin.url", {
15
- cwd: repoPath,
16
- })
17
- .toString()
18
- .trim();
19
- const { owner, repo } = (0, utils_1.parseGitHubUrl)(remoteUrl);
20
- const branchName = await (0, git_1.getCurrentBranchName)(repoPath);
21
- (0, child_process_1.execSync)(`git push origin ${branchName} --set-upstream`, {
22
- cwd: repoPath,
23
- });
24
- if (!apiClient) {
25
- throw new Error("Dashboard API client is not available.");
26
- }
27
- let pullRequest = await (0, utils_1.getExistingPR)({
28
- owner,
29
- repo,
30
- branchName,
31
- apiClient,
32
- });
33
- if (pullRequest) {
34
- pullRequest = await (0, utils_1.updatePullRequest)({
35
- owner,
36
- repo,
37
- prNumber: pullRequest.number,
38
- body: (0, pr_description_1.addMetadataToPRDescription)(pullRequestDescription, chatSession),
39
- apiClient,
40
- });
41
- const mergeableState = await (0, utils_1.getMergeableState)({
42
- owner,
43
- repo,
44
- pullRequest,
45
- apiClient,
46
- });
47
- const stateDescription = (0, utils_1.getMergeableStateDescription)(mergeableState);
48
- return {
49
- isError: false,
50
- result: `Updated existing PR: ${pullRequest.html_url}\n\nMergeable state: ${mergeableState} - ${stateDescription}`,
51
- };
52
- }
53
- else {
54
- pullRequest = await (0, utils_1.createPullRequest)({
55
- owner,
56
- repo,
57
- title: pullRequestTitle,
58
- head: branchName,
59
- base: "main",
60
- body: (0, pr_description_1.addMetadataToPRDescription)(pullRequestDescription, chatSession),
61
- apiClient,
62
- });
63
- const mergeableState = await (0, utils_1.getMergeableState)({
64
- owner,
65
- repo,
66
- pullRequest,
67
- apiClient,
68
- });
69
- const stateDescription = (0, utils_1.getMergeableStateDescription)(mergeableState);
70
- return {
71
- isError: false,
72
- result: `Created a new PR: ${pullRequest.html_url}\n\nMergeable state: ${mergeableState} - ${stateDescription}`,
73
- };
74
- }
75
- }
76
- catch (error) {
77
- return {
78
- isError: true,
79
- result: `Failed to commit and push changes: ${error instanceof Error ? error.message : String(error)}`,
80
- };
81
- }
82
- },
83
- };
@@ -1,3 +0,0 @@
1
- import type { ToolDefinition } from "@empiricalrun/shared-types";
2
- export declare const createPullRequestTool: ToolDefinition;
3
- //# sourceMappingURL=commit-and-create-pr.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"commit-and-create-pr.d.ts","sourceRoot":"","sources":["../../../src/tools/definitions/commit-and-create-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAmBjE,eAAO,MAAM,qBAAqB,EAAE,cAenC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/fetch-image/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA8B,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,gBAAgB;;;;;;EAEpB,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAuDjE,CAAC"}
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchImageTool = void 0;
4
- const zod_1 = require("zod");
5
- const SUPPORTED_CONTENT_TYPES = ["image/png", "image/jpeg"];
6
- const fetchImageSchema = zod_1.z.object({
7
- url: zod_1.z.string(),
8
- });
9
- exports.fetchImageTool = {
10
- schema: {
11
- name: "fetchImage",
12
- description: `Use this tool to fetch image data from any valid URL that responds with a PNG or JPEG image.
13
- It takes an image URL as input and returns the image in base64 format, for you to view or analyze.
14
-
15
- ## Common scenarios:
16
- 1. Understand a test report (for the runTest tool) by fetching screenshots: test results can have screenshot URLs in the attachments section of the report.
17
-
18
- 2. While adding new tests, if the user message contains image URLs, use this tool to fetch the images, and understand the steps that the user is looking to cover.`,
19
- parameters: fetchImageSchema,
20
- },
21
- needsBrowser: false,
22
- isInlineTool: true,
23
- execute: async ({ input }) => {
24
- const { url } = input;
25
- try {
26
- const response = await fetch(url);
27
- if (!response.ok) {
28
- console.error(`Failed to fetch image from ${url}: ${response.statusText}`);
29
- return {
30
- result: `Failed to fetch image from ${url}: ${response.statusText}`,
31
- isError: true,
32
- };
33
- }
34
- const contentType = response.headers.get("content-type");
35
- if (!contentType || !SUPPORTED_CONTENT_TYPES.includes(contentType)) {
36
- const errorMessage = `Invalid content type: ${contentType}. URL must return an image.`;
37
- console.error(errorMessage);
38
- return {
39
- result: errorMessage,
40
- isError: true,
41
- };
42
- }
43
- const buffer = await response.arrayBuffer();
44
- const base64 = Buffer.from(buffer).toString("base64");
45
- return {
46
- result: [
47
- {
48
- type: contentType,
49
- base64Data: base64,
50
- },
51
- ],
52
- isError: false,
53
- };
54
- }
55
- catch (error) {
56
- console.error("Error fetching image", error);
57
- return {
58
- result: `Error fetching image: ${error}`,
59
- isError: true,
60
- };
61
- }
62
- },
63
- };
@@ -1,24 +0,0 @@
1
- export declare class LocalFFmpegClient {
2
- private static readonly MAX_VIDEO_DURATION_SECONDS;
3
- private static readonly CHUNK_DURATION_SECONDS;
4
- constructor();
5
- private checkFFmpegAvailability;
6
- private getVideoDuration;
7
- private validateVideoChunk;
8
- private downloadVideo;
9
- private createVideoChunks;
10
- private extractFramesToFiles;
11
- private processVideoChunks;
12
- extractVideoFrames(videoUrl: string, outputDir: string): Promise<{
13
- totalFramesCount: number;
14
- uniqueFramesCount: number;
15
- uniqueFrames: {
16
- metadata: {
17
- index: number;
18
- path: string;
19
- };
20
- image: string;
21
- }[];
22
- }>;
23
- }
24
- //# sourceMappingURL=local-ffmpeg-client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-ffmpeg-client.d.ts","sourceRoot":"","sources":["../../../src/tools/fetch-video-analysis/local-ffmpeg-client.ts"],"names":[],"mappings":"AASA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAW;IAC7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAU;;IAMxD,OAAO,CAAC,uBAAuB;YAWjB,gBAAgB;YAiBhB,kBAAkB;YAgClB,aAAa;YAeb,iBAAiB;YAoDjB,oBAAoB;YAiCpB,kBAAkB;IAyD1B,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE;YACZ,QAAQ,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,CAAC;YAC1C,KAAK,EAAE,MAAM,CAAC;SACf,EAAE,CAAC;KACL,CAAC;CAgEH"}